Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
eaed6b4
Declare com.google.android.gms.permission.CAR_SPEED permission
DaVinci9196 Dec 19, 2023
6f624a1
Fix the problem that Tasks&Jamboard&Fitbit App cannot log in with Google
DaVinci9196 Jan 26, 2024
e8dc0a0
Merge remote-tracking branch 'origin/master'
DaVinci9196 Apr 17, 2024
a8a2cfa
add Scope.aidl
DaVinci9196 Apr 19, 2024
124f7d1
Merge branch 'microg:master' into master
DaVinci9196 May 7, 2024
34ccbe2
SplitInstallService Additions
DaVinci9196 Aug 19, 2024
5e6f01e
add permission
DaVinci9196 Aug 19, 2024
1962f33
ISplitInstallServiceCallback added
DaVinci9196 Aug 19, 2024
c9bfbc0
remove Phenotype / Experiment
DaVinci9196 Aug 21, 2024
796c3ab
Merge branch 'microg:master' into split_install_service
DaVinci9196 Aug 22, 2024
e8a0058
Optimizing the code
DaVinci9196 Aug 22, 2024
b8d2b20
SplitInstallService add call super.onBind
DaVinci9196 Aug 22, 2024
6cdd488
Fixed the issue that multiple versions of language packs could not be…
DaVinci9196 Aug 26, 2024
36651db
Formatting Code
DaVinci9196 Aug 27, 2024
ff837d9
Formatting Code
DaVinci9196 Aug 27, 2024
8a68044
Execute processing suggestions
DaVinci9196 Sep 12, 2024
5a9f1b3
cleanup
DaVinci9196 Sep 12, 2024
7df6f93
Location/Huawei: Fix permission notification cancelling
mar-v-in Aug 22, 2024
bc57d78
Added the automatic login function for Games (#2435)
DaVinci9196 Aug 22, 2024
a7a2584
Location: Make sure current interval and configured interval stay in …
mar-v-in Aug 22, 2024
c5b7383
Create Work Account service
fynngodau Sep 20, 2023
686ab6d
Introduce WorkAccountAuthenticatorService
jonathanklee Aug 14, 2024
96e6b0c
Work account POC
fynngodau Aug 27, 2024
7f4f252
Work profile: use correct AIDL
fynngodau Aug 27, 2024
762fa53
Call account creation when app is using API to create work account
fynngodau Sep 1, 2024
999e1d3
Work account: Fix rough edges
fynngodau Sep 1, 2024
3af3991
Work account: Add security checks
fynngodau Sep 1, 2024
5e2c9d3
Work account: Redeem token when signing in to account
fynngodau Sep 2, 2024
3128c06
Add license identifiers and remove unwanted changes
fynngodau Sep 2, 2024
30f4858
Work account: Fix `NewApi` lint failure
fynngodau Sep 2, 2024
482038a
Deduplicate work account service declaration
fynngodau Sep 13, 2024
5a39c65
POC: Test activity in companion app to show client policy
fynngodau Sep 14, 2024
0db6eed
Improve visuals of vending activity
fynngodau Sep 15, 2024
c621098
Fetch bulk details for apps retrieved from policy
fynngodau Sep 15, 2024
1e17cc1
Load app details using getItems
fynngodau Sep 16, 2024
8e5ca13
Cleanup: Remove nonfunctional bulkDetails request
fynngodau Sep 16, 2024
20e04fe
UI: Add download button
fynngodau Sep 16, 2024
e99cbd3
Fetch app download URLs
fynngodau Sep 20, 2024
80c9c52
Add app installation support
fynngodau Sep 21, 2024
7ab6cf1
Add app uninstallation support
fynngodau Sep 21, 2024
c3398b9
Refactor SplitInstallManager: data types
fynngodau Sep 21, 2024
3edeb83
Refactor SplitInstallManager: structural pt. 1
fynngodau Sep 21, 2024
23d4459
`FLAG_MUTABLE` instead of `FLAG_IMMUTABLE`
fynngodau Sep 21, 2024
e434c8c
Refactor SplitInstallManager: structural pt. 2
fynngodau Sep 21, 2024
73f1a3a
Refactor SplitInstallManager: structural pt. 3
fynngodau Sep 22, 2024
3b8509d
Work vending: Show installation success without reload
fynngodau Sep 22, 2024
68ef487
Use cache dir instead of files dir
fynngodau Sep 22, 2024
f257e83
Enable work app store only after adding a work account
fynngodau Sep 22, 2024
1887759
Fix lint
fynngodau Sep 22, 2024
85bd1c9
Fix split installs
fynngodau Sep 22, 2024
2e1dfec
Organize vending protobuf files
fynngodau Sep 25, 2024
ec18cdb
Replace volley with ktor + okhttp
fynngodau Sep 25, 2024
09acd1a
Install packages directly to improve performance
fynngodau Sep 25, 2024
9ee71fb
Add progress bar to work app store
fynngodau Sep 26, 2024
352260d
Reimplement caching in `HttpClient`
fynngodau Sep 26, 2024
2109e46
Discard session after exception to clear up storage
fynngodau Sep 26, 2024
c237146
Notifications upon install progress
fynngodau Oct 1, 2024
f39a889
Deduplicate auth-related files
fynngodau Oct 19, 2024
c976df1
Clean up constants
fynngodau Oct 19, 2024
f14124c
Merge master branch into workaccount-store
fynngodau Oct 19, 2024
655cc6f
Fix crash when no apps in enterprise policy
fynngodau Oct 19, 2024
4f0665c
Fix build
fynngodau Oct 19, 2024
a6dc3b3
Purchase apps before downloading in work store
fynngodau Oct 19, 2024
b2cec33
Support additional strange behaviors
fynngodau Oct 19, 2024
04afa56
Show info: wait before work app store can be used
fynngodau Oct 21, 2024
ed745dc
Apply review
fynngodau Oct 28, 2024
be13514
Merge branch 'microg:master' into master
DaVinci9196 Nov 1, 2024
5f2430e
Merge branch 'microg:master' into master
DaVinci9196 Feb 19, 2025
27d08f4
splite module optimization, including synchronization and bulk grant
DaVinci9196 Feb 19, 2025
006883c
Fixed the issue of Split repeatedly downloading due to repeated inter…
DaVinci9196 Feb 19, 2025
c3e74ab
split notification setOngoing set is false
DaVinci9196 Feb 19, 2025
8cfe5fb
Click the notification to install on the screen off
DaVinci9196 Feb 19, 2025
845f6d4
Optimize split download link filtering conditions
DaVinci9196 Feb 19, 2025
c1741f5
request header add languages
DaVinci9196 Feb 20, 2025
c40aa71
Add breakpoint resume function to optimize download traffic consumption
DaVinci9196 Feb 21, 2025
1a915cc
Generate a notifyId based on the package name and download module to …
DaVinci9196 Feb 22, 2025
70a8ddd
Switch for on-demand downloading of specific app features
DaVinci9196 Feb 24, 2025
8034621
Fix the download progress bar display issue
DaVinci9196 Feb 19, 2025
c36f388
Merge branch 'refs/heads/master' into fix_split_installs
DaVinci9196 Feb 28, 2025
608c606
Merge the master branch and resolve conflicts
DaVinci9196 Feb 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ buildscript {

ext.slf4jVersion = '1.7.36'
ext.volleyVersion = '1.2.1'
ext.wireVersion = '4.8.0'
ext.tinkVersion = '1.13.0'
ext.okHttpVersion = '4.12.0'
ext.ktorVersion = '2.3.12'
ext.wireVersion = '4.9.9'

ext.androidBuildGradleVersion = '8.2.2'

Expand Down
38 changes: 38 additions & 0 deletions play-services-auth-workaccount/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* SPDX-FileCopyrightText: 2023 e foundation
* SPDX-License-Identifier: Apache-2.0
*/

apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
apply plugin: 'signing'

android {
namespace "com.google.android.gms.auth.workaccount"

compileSdkVersion androidCompileSdk
buildToolsVersion "$androidBuildVersionTools"

buildFeatures {
aidl = true
}

defaultConfig {
versionName version
minSdkVersion androidMinSdk
targetSdkVersion androidTargetSdk
}

compileOptions {
sourceCompatibility = 1.8
targetCompatibility = 1.8
}

}

apply from: '../gradle/publish-android.gradle'

description = 'microG implementation of managed work account support'

dependencies {
}
45 changes: 45 additions & 0 deletions play-services-auth-workaccount/core/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* SPDX-FileCopyrightText: 2023 e foundation
* SPDX-License-Identifier: Apache-2.0
*/

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

dependencies {
api project(':play-services-auth-workaccount')
api project(':play-services-auth')
implementation project(':play-services-base-core')

implementation "androidx.appcompat:appcompat:$appcompatVersion"
}

android {
namespace "com.google.android.gms.auth.workaccount"

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
}

lintOptions {
disable 'MissingTranslation'
}
}
49 changes: 49 additions & 0 deletions play-services-auth-workaccount/core/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2023 e foundation
~ SPDX-License-Identifier: Apache-2.0
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<uses-permission
android:name="android.permission.AUTHENTICATE_ACCOUNTS"
android:maxSdkVersion="22" />
<uses-permission
android:name="android.permission.GET_ACCOUNTS"
android:maxSdkVersion="22" />
<uses-permission
android:name="android.permission.MANAGE_ACCOUNTS"
android:maxSdkVersion="22" />

<application>

<service android:name="org.microg.gms.auth.workaccount.WorkAccountService"
android:exported="true">
<intent-filter>
<action android:name="com.google.android.gms.auth.account.workaccount.START" />
</intent-filter>
</service>

<service
android:name="com.google.android.gms.auth.account.authenticator.WorkAccountAuthenticatorService"
android:process=":persistent"
android:enabled="false"
android:exported="false">

<intent-filter>
<action android:name="android.accounts.AccountAuthenticator"/>
</intent-filter>

<meta-data
android:name="android.accounts.AccountAuthenticator"
android:resource="@xml/auth_work_authenticator"/>

<meta-data
android:name="android.accounts.AccountAuthenticator.customTokens"
android:value="1"/>

</service>

</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
/*
* SPDX-FileCopyrightText: 2024 e foundation
* SPDX-License-Identifier: Apache-2.0
*/

package com.google.android.gms.auth.account.authenticator

import android.accounts.AbstractAccountAuthenticator
import android.accounts.Account
import android.accounts.AccountAuthenticatorResponse
import android.accounts.AccountManager
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.util.Log
import com.google.android.gms.auth.workaccount.R
import org.microg.gms.auth.AuthConstants
import org.microg.gms.common.PackageUtils
import org.microg.gms.auth.AuthRequest
import org.microg.gms.auth.AuthResponse
import java.io.IOException
import kotlin.jvm.Throws

class WorkAccountAuthenticator(val context: Context) : AbstractAccountAuthenticator(context) {

override fun editProperties(
response: AccountAuthenticatorResponse,
accountType: String?
): Bundle {
TODO("Not yet implemented: editProperties")
}

override fun addAccount(
response: AccountAuthenticatorResponse,
accountType: String,
authTokenType: String?,
requiredFeatures: Array<out String>?,
options: Bundle
): Bundle? {
if (
!options.containsKey(KEY_ACCOUNT_CREATION_TOKEN)
|| options.getString(KEY_ACCOUNT_CREATION_TOKEN) == null
|| options.getInt(AccountManager.KEY_CALLER_UID) != android.os.Process.myUid()) {
Log.e(TAG,
"refusing to add account without creation token or from external app: " +
"could have been manually initiated by user (not supported) " +
"or by unauthorized app (not allowed)"
)

// TODO: The error message is not automatically displayed by the settings app as of now.
// We can consider showing the error message through a popup instead.

return Bundle().apply {
putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION)
putString(AccountManager.KEY_ERROR_MESSAGE, context.getString(R.string.auth_work_authenticator_add_manual_error)
)
}
}

val oauthToken: String = options.getString(KEY_ACCOUNT_CREATION_TOKEN)!!

try {
tryAddAccount(oauthToken, response)
} catch (exception: Exception) {
response.onResult(Bundle().apply {
putInt(
AccountManager.KEY_ERROR_CODE,
AccountManager.ERROR_CODE_NETWORK_ERROR
)
putString(AccountManager.KEY_ERROR_MESSAGE, exception.message)
})
}

/* Note: as is not documented, `null` must only be returned after `response.onResult` was
* already called, hence forcing the requests to be synchronous. They are still async to
* the caller's main thread because AccountManager forces potentially blocking operations,
* like waiting for a response upon `addAccount`, not to be on the main thread.
*/
return null
}

@Throws(Exception::class)
private fun tryAddAccount(
oauthToken: String,
response: AccountAuthenticatorResponse
) {
val authResponse = AuthRequest().fromContext(context)
.appIsGms()
.callerIsGms()
.service("ac2dm")
.token(oauthToken).isAccessToken()
.addAccount()
.getAccountId()
.droidguardResults(null)
.response

val accountManager = AccountManager.get(context)
if (accountManager.addAccountExplicitly(
Account(authResponse.email, AuthConstants.WORK_ACCOUNT_TYPE),
authResponse.token, Bundle().apply {
// Work accounts have no SID / LSID ("BAD_COOKIE") and no first/last name.
if (authResponse.accountId.isNotBlank()) {
putString(KEY_GOOGLE_USER_ID, authResponse.accountId)
}
putString(AuthConstants.KEY_ACCOUNT_CAPABILITIES, authResponse.capabilities)
putString(AuthConstants.KEY_ACCOUNT_SERVICES, authResponse.services)
if (authResponse.services != "android") {
Log.i(
TAG,
"unexpected 'services' value ${authResponse.services} (usually 'android')"
)
}
}
)
) {

// Notify vending package
context.sendBroadcast(
Intent(WORK_ACCOUNT_CHANGED_BOARDCAST).setPackage("com.android.vending")
)

// Report successful creation to caller
response.onResult(Bundle().apply {
putString(AccountManager.KEY_ACCOUNT_NAME, authResponse.email)
putString(AccountManager.KEY_ACCOUNT_TYPE, AuthConstants.WORK_ACCOUNT_TYPE)
})
}
}

override fun confirmCredentials(
response: AccountAuthenticatorResponse?,
account: Account?,
options: Bundle?
): Bundle {
return Bundle().apply {
putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true)
}
}

override fun getAuthToken(
response: AccountAuthenticatorResponse?,
account: Account,
authTokenType: String?,
options: Bundle?
): Bundle {
try {
val authResponse: AuthResponse =
AuthRequest().fromContext(context)
.source("android")
.app(
context.packageName,
PackageUtils.firstSignatureDigest(context, context.packageName)
)
.email(account.name)
.token(AccountManager.get(context).getPassword(account))
.service(authTokenType)
.delegation(0, null)
// .oauth2Foreground(oauth2Foreground)
// .oauth2Prompt(oauth2Prompt)
// .oauth2IncludeProfile(includeProfile)
// .oauth2IncludeEmail(includeEmail)
// .itCaveatTypes(itCaveatTypes)
// .tokenRequestOptions(tokenRequestOptions)
.systemPartition(true)
.hasPermission(true)
// .putDynamicFiledMap(dynamicFields)
.appIsGms()
.callerIsApp()
.response

return Bundle().apply {
putString(AccountManager.KEY_ACCOUNT_NAME, account.name)
putString(AccountManager.KEY_ACCOUNT_TYPE, account.type)
putString(AccountManager.KEY_AUTHTOKEN, authResponse.auth)
}
} catch (e: IOException) {
return Bundle().apply {
putInt(AccountManager.KEY_ERROR_CODE, AccountManager.ERROR_CODE_NETWORK_ERROR)
putString(AccountManager.KEY_ERROR_MESSAGE, e.message)
}
}
}

override fun getAuthTokenLabel(authTokenType: String?): String {
TODO("Not yet implemented: getAuthTokenLabel")
}

override fun updateCredentials(
response: AccountAuthenticatorResponse?,
account: Account?,
authTokenType: String?,
options: Bundle?
): Bundle {
TODO("Not yet implemented: updateCredentials")
}

override fun hasFeatures(
response: AccountAuthenticatorResponse?,
account: Account?,
features: Array<out String>
): Bundle {
Log.i(TAG, "Queried features: " + features.joinToString(", "))
return Bundle().apply {
putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)
}
}

/**
* Prevent accidental deletion, unlike GMS. The account can only be removed through client apps;
* ideally, it would only be removed by the app that requested it to be created / the DPC
* manager, though this is not enforced. On API 21, the account can also be removed by hand
* because `removeAccountExplicitly` is not available on API 21.
*/
override fun getAccountRemovalAllowed(
response: AccountAuthenticatorResponse?,
account: Account?
): Bundle {
return Bundle().apply {
putBoolean(AccountManager.KEY_BOOLEAN_RESULT,
Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1
)
}
}

companion object {
const val TAG = "WorkAccAuthenticator"

const val WORK_ACCOUNT_CHANGED_BOARDCAST = "org.microg.vending.WORK_ACCOUNT_CHANGED"

const val KEY_ACCOUNT_CREATION_TOKEN = "creationToken"
private const val KEY_GOOGLE_USER_ID = AuthConstants.GOOGLE_USER_ID
}
}
Loading
Loading