Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Implement Licensing service #2069

Merged
merged 24 commits into from
Feb 16, 2024
Merged

Implement Licensing service #2069

merged 24 commits into from
Feb 16, 2024

Conversation

fynngodau
Copy link
Contributor

@fynngodau fynngodau commented Oct 4, 2023

Implemented as of now:

  • Licensing requests
  • Query multiple Google accounts
  • If no Google account is registered, show a notification
  • Query profile service
  • Query preference for whether licensing is enabled

@ale5000-git
Copy link
Member

Hi,
is there a real need to bump JavaVersion?

@ale5000-git
Copy link
Member

Also FakeStore can have a different signature of GmsCore and in this case maxSdkVersion on android.permission.GET_ACCOUNTS can break things.

@fynngodau
Copy link
Contributor Author

Hi,
is there a real need to bump JavaVersion?

With the current Kotlin version, which needs to be included for wire (protobuf library), it seems that yes.

Also FakeStore can have a different signature of GmsCore and in this case maxSdkVersion on android.permission.GET_ACCOUNTS can break things.

I will remove the attribute.

@mar-v-in
Copy link
Member

mar-v-in commented Oct 4, 2023

If you configure kotlin to be JVM 8 compatible, you can keep Java Version to 8 as well. We do the same everywhere else

    kotlinOptions {
        jvmTarget = 1.8
    }

@fynngodau
Copy link
Contributor Author

@mar-v-in Thanks, applied.

@ale5000-git
Copy link
Member

It isn't really a problem for me, bit since it contact a Google server many people would probably like to have a setting for it (disabled by default)

@fynngodau
Copy link
Contributor Author

@ale5000-git Since fakestore doesn't have a UI, a setting for this can't easily be implemented. Note that the licensing request is only made if a Google account has been added. (Apps are also expected to have the com.android.vending.CHECK_LICENSE permission, but they can acquire it just by declaring it; I just added a commit that enforces that they have it.)

@fynngodau fynngodau mentioned this pull request Oct 22, 2023
@fynngodau
Copy link
Contributor Author

@ale5000-git Setting is added to UI in #2076.

@ale5000-git
Copy link
Member

Now we need the code that checks for the preference since #2076 is merged :-)

@fynngodau
Copy link
Contributor Author

Now we need the code that checks for the preference since #2076 is merged :-)

You are absolutely right. I'm getting all confused here with the many branches I'm handling. What is pushed now should make sense but maybe I got something confused yet again 😞

@ale5000-git
Copy link
Member

I cannot test it currently but it seems fine 😃

@ale5000-git
Copy link
Member

Just noticed a minor comment issue, here: https://github.com/microg/GmsCore/pull/2069/files#diff-93490511fa787a3e0c583ec081e5e22c2e49da9a8688b70db5b99168fbc7f7bcR40

NOT_LICENSED => The application is licensed to the user, but there is an updated application version ...

LICENSED_OLD_KEY => The application is not licensed to the user

Only the opposite make sense.

@ale5000-git
Copy link
Member

@ale5000-git
Copy link
Member

@fynngodau
In case you haven't yet noticed also this PR was already merged: #2071

@fynngodau
Copy link
Contributor Author

Only the opposite make sense.

@ale5000-git Thank you, seems I swapped them on accident.

In case you haven't yet noticed also this PR was already merged: #2071

Yes, I noticed, I was just very busy and had no time to update this PR like planned. It should be good now, but I don't have the time to test the latest state as well as would be desirable.

@@ -70,7 +70,7 @@ public void run() {
ignoreIntent.putExtra(INTENT_KEY_IGNORE_PACKAGE_NAME, callerPackageName);
ignoreIntent.putExtra(INTENT_KEY_NOTIFICATION_ID, callerUid);
PendingIntent ignorePendingIntent = PendingIntent.getBroadcast(
context, callerUid * 2 + 1, ignoreIntent, PendingIntent.FLAG_IMMUTABLE
context, callerUid * 2 + 1, ignoreIntent, PendingIntent.FLAG_MUTABLE
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not one bit of an idea why, in my emulator tests, the INTENT_KEY_IGNORE_PACKAGE_NAME extra doesn't reach the receiver when FLAG_IMMUTABLE is set.

@@ -17,6 +17,8 @@ android {
versionCode vendingAppVersionCode
minSdkVersion androidMinSdk
targetSdkVersion androidTargetSdk

multiDexEnabled true
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems the pipeline is failing due to the 65,536 method limit? I'm quite confused, as this is not happening locally. Anyhow, this commit is supposed to enable multidex, but I'm unsure if that's an appropriate solution in this case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now it have this lint error:

/home/runner/work/GmsCore/GmsCore/vending-app/src/main/java/com/android/vending/licensing/LicenseServiceNotificationRunnable.java:95:
Error: Call requires permission which may be rejected by user:
code should explicitly check to see if permission is available (with checkPermission)
or explicitly handle a potential SecurityException [MissingPermission]
          notificationManager.notify(callerUid, notification);

Did you run also lint locally?

Copy link
Contributor Author

@fynngodau fynngodau Jan 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ale5000-git I noticed the pipeline failing, but no, I haven't run the lint locally. I likely won't have time to fix this issue in the next days.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem, take your time.
Your contribution is really appreciated.

@fynngodau
Copy link
Contributor Author

With the notifications lint issue solved, here comes the next lint issue:


> Task :vending-app:lintDefaultDebug FAILED
Lint found 1 errors, 4 warnings. First failure:

/home/runner/work/GmsCore/GmsCore/vending-app/src/main/res/values-ast: Error: The app will crash on platforms older than v21 (minSdkVersion is 14) because AssetManager#getLocales() is called (from the library jar file jars/classes.jar) and this folder resource name only works on v21 or later with that call present in the app [GetLocales]

   Explanation for issues of type "GetLocales":
   This check looks for usage of Lollipop-style locale folders (e.g. 3 letter
   language codes, or BCP 47 qualifiers) combined with an
   AssetManager#getLocales() call. This leads to crashes

I'm, uh, again, not sure why this is coming up even though the folder exists since 93e4884, which is included in master, and what a recommended solution would be.

@ale5000-git
Copy link
Member

@fynngodau
You probably need to do something similar to this: f0b15d2

@mar-v-in
Copy link
Member

The GetLocales lint is a little bit buggy. It is triggered by the call to getLocales in play-services-base which has proper SDK version checks in place. However the lint check not only applies to source code, but also to binary dependencies. During the build process, play-services-base is built into a jar binary jars/classes.jar, that is then used from other modules (vending-app in this case). However the linter does not analyze the binary code in the same was as source code to determine if the call to getLocales has proper SDK version checks (or to look for @SuppressLint annotations).

That's why it triggers this lint in every submodule that uses play-services-base. The only thing we can do is to ignore the lint check.

@fynngodau
Copy link
Contributor Author

@ale5000-git @mar-v-in Thanks for the pointer and explanation. I have disabled the faulty lint.

@ale5000-git
Copy link
Member

@fynngodau
Regarding the 65.536 method limit issue this is what I have understood:
When you include a library, even if you only use a single method, the final file will also include the unused methods, so this will likely cause the limit to be exceeded.
Multidex may cause additional problems on older Android versions so if possible it is better to avoid it as FakeStore shouldn't be that big.

An alternative could be to enable minifyEnabled which will strip unused code, decreasing the number of methods and the final size.

@mar-v-in
What do you think about enabling minifyEnabled in FakeStore?

@mar-v-in
Copy link
Member

mar-v-in commented Jan 23, 2024

I'm fine with using Proguard to remove unused methods or classes to reduce file size, however note that doing so imposes the risk to remove actually used methods. As soon as reflection is in place, proguard might be behaving wrong. So you need to take care of proper testing every functionality when activating it.

I don't like the renaming and obfuscation that comes with proguard / r8 minification. I'm pretty sure it can be turned off though. Renaming/obfuscation may add nondeterminism and generally makes it harder to link the resulting binary and it's behavior to the source code, which IMO is an important .

However, I also don't see any issue with using Multidex. I'm not aware of it causing issues in older versions as long as the androidx multidex support library is used correctly on SDK > 14, which is already our min sdk.

@ale5000-git
Copy link
Member

Is there any use or need of reflection in FakeStore?

About renaming and obfuscation I agree.

The main issue with multidex on old Android versions is that some methods must be in the first dex and the developer must figure it himself otherwise it break without anyone noticing it (if it just break less used features).

@mar-v-in
Copy link
Member

The main issue with multidex on old Android versions is that some methods must be in the first dex and the developer must figure it himself otherwise it break without anyone noticing it

This shouldn't happen a lot in practice. The app's Application class is loaded first and the build system tries to include it and all the code it uses in the primary classes.dex. The app's Application runs the multidex library code to load the other dex files.

There are two cases not covered by this:

  • A custom Application class that runs code via reflection (which might be undetected by the build system)
  • Third-party code loading the app's classes.dex without running the multidex loader.

The latter is what we've seen in practice causing issues in microG, partially because we don't correctly implement the dynamite loader (which should take care of loading the correct dex files as well). However third-parties are not supposed to load code from the vending package, so this shouldn't be relevant here.

@ale5000-git
Copy link
Member

Instead of minifyEnabled to get minify without obfuscation we can use:

postprocessing {
    removeUnusedCode true
    removeUnusedResources true
    obfuscate false
    optimizeCode true
}

@ale5000-git
Copy link
Member

@mar-v-in
There is a pull request that was abandoned but we may need it before or later: microg/FakeStore#35
I'm not sure if this load code from the vending package.

@mar-v-in
Copy link
Member

removeUnusedResources would probably break things in play-services-core, but should be fine here.

The split install service is a service, which is part of the Application. Loading code directly is when the API does not use IPC, but loads and executes the code inside the third-party app itself. This happens for Maps SDK, security provider, cronet, Vision APIs and a few others that are loaded using dynamite.

@ale5000-git
Copy link
Member

ale5000-git commented Jan 23, 2024

In addition to other advantages I think it will also improve performance if there is a single dex and it is small (expecially on 1GB devices where the memory is also slow).

If I'm not wrong beside install referrer, dummy in-app billing and this license code there is basically nothing in FakeStore so I suggest to enable this now (since currently it should be really easy to test regressions).

@fynngodau
Copy link
Contributor Author

@ale5000-git Multidex is now disabled, and postprocessing as you suggested is now enabled.

@ale5000-git
Copy link
Member

@fynngodau
I'm not sure why but on Windows building it with this command:
gradlew clean :vending-app:assembleDefaultRelease
will result in this error:
ERROR: C:\Users\MyUser\Documents\GmsCore\play-services-auth-api-phone\build\generated\aidl_source_output_dir\release\out\com\google\android\gms\auth\api\phone\internal\IAutofillPermissionStateCallback.java: Failed to GetFullPathName

@mar-v-in mar-v-in merged commit 62081a8 into microg:master Feb 16, 2024
1 check passed
@fynngodau fynngodau deleted the licensing branch February 16, 2024 21:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants