Skip to content

Commit

Permalink
Optimize code logic
Browse files Browse the repository at this point in the history
  • Loading branch information
DaVinci9196 committed Nov 8, 2024
1 parent aa53053 commit 71a8f59
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import android.graphics.Canvas
import android.graphics.drawable.BitmapDrawable
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
Expand Down Expand Up @@ -55,7 +54,7 @@ class DownloadManager(private val context: Context) {
private val downloadingRecord = ConcurrentHashMap<String, Future<*>>()

@Volatile
private var shouldStop = false
private var shouldStops = false

private val cancelReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Expand Down Expand Up @@ -145,14 +144,18 @@ class DownloadManager(private val context: Context) {
NotificationManagerCompat.from(context).notify(NOTIFICATION_ID, notifyBuilder.setCustomContentView(notificationLayout).build())
}

@Synchronized
fun shouldStop(shouldStop:Boolean){
shouldStops = shouldStop
}

@Synchronized
fun prepareDownload(downloadData: DownloadData, moduleName: String) {
Log.d(TAG, "prepareDownload: ${downloadData.packageName}")
shouldStop = false
downloadData.updateDownloadStatus(moduleName, STATUS_DOWNLOADING)
initNotification(moduleName, downloadData.packageName)
val future = executor.submit {
val packData = downloadData.getModuleData(moduleName)
downloadData.updateDownloadStatus(moduleName, STATUS_DOWNLOADING)
for (dataBundle in packData.packBundleList) {
val resourcePackageName: String? = dataBundle.getString(KEY_RESOURCE_PACKAGE_NAME)
val chunkName: String? = dataBundle.getString(KEY_CHUNK_NAME)
Expand All @@ -178,7 +181,7 @@ class DownloadManager(private val context: Context) {
private fun cancelDownload(moduleName: String) {
Log.d(TAG, "Download for module $moduleName has been canceled.")
downloadingRecord[moduleName]?.cancel(true)
shouldStop = true
shouldStops = true
notifyBuilderMap[moduleName]?.setOngoing(false)
NotificationManagerCompat.from(context).cancel(NOTIFICATION_ID)
}
Expand All @@ -205,7 +208,7 @@ class DownloadManager(private val context: Context) {
val buffer = ByteArray(4096)
var bytesRead: Int
while (input.read(buffer).also { bytesRead = it } != -1) {
if (shouldStop) {
if (shouldStops) {
Log.d(TAG, "Download interrupted for module: $moduleName")
downloadData.updateDownloadStatus(moduleName, CANCELED)
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import android.util.Log
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleService
import androidx.lifecycle.lifecycleScope
import com.google.android.finsky.DownloadManager
import com.google.android.finsky.ERROR_CODE_FAIL
import com.google.android.finsky.KEY_BYTE_LENGTH
Expand All @@ -36,7 +35,6 @@ import com.google.android.finsky.KEY_SLICE_ID
import com.google.android.finsky.STATUS_COMPLETED
import com.google.android.finsky.STATUS_DOWNLOADING
import com.google.android.finsky.STATUS_INITIAL_STATE
import com.google.android.finsky.STATUS_NOT_INSTALLED
import com.google.android.finsky.TAG_REQUEST
import com.google.android.finsky.buildDownloadBundle
import com.google.android.finsky.initAssertModuleData
Expand Down Expand Up @@ -82,79 +80,39 @@ class AssetModuleServiceImpl(
callback?.onError(Bundle().apply { putInt(KEY_ERROR_CODE, -5) })
return
}
lifecycleScope.launchWhenStarted {
if (downloadData == null || downloadData?.packageName != packageName) {
val requestedAssetModuleNames = list.map { it.getString(KEY_MODULE_NAME) }.filter { !it.isNullOrEmpty() }
val playCoreVersionCode = bundle.getInt(KEY_PLAY_CORE_VERSION_CODE)
downloadData = httpClient.initAssertModuleData(context, packageName, accountManager, requestedAssetModuleNames, playCoreVersionCode)
}
if (list.all { it.getString(KEY_MODULE_NAME) == null } || moduleErrorRequested.contains(packageName)) {
Log.d(TAG, "startDownload: moduleData request error")
val result = Bundle().apply { putStringArrayList(KEY_PACK_NAMES, arrayListOf<String>()) }
callback?.onStartDownload(-1, result)
return@launchWhenStarted
}
list.forEach {
val moduleName = it.getString(KEY_MODULE_NAME)
val packData = downloadData?.getModuleData(moduleName!!)
if (packData?.status != STATUS_DOWNLOADING){
downloadData?.updateDownloadStatus(moduleName!!, STATUS_INITIAL_STATE)
}
if (downloadData == null || downloadData?.packageName != packageName) {
val requestedAssetModuleNames = list.map { it.getString(KEY_MODULE_NAME) }.filter { !it.isNullOrEmpty() }
val playCoreVersionCode = bundle.getInt(KEY_PLAY_CORE_VERSION_CODE)
downloadData = httpClient.initAssertModuleData(context, packageName, accountManager, requestedAssetModuleNames, playCoreVersionCode)
}
list.forEach {
val moduleName = it.getString(KEY_MODULE_NAME)
val packData = downloadData?.getModuleData(moduleName!!)
if (packData?.status != STATUS_DOWNLOADING && packData?.status != STATUS_COMPLETED){
downloadData?.updateDownloadStatus(moduleName!!, STATUS_INITIAL_STATE)
}
val bundleData = buildDownloadBundle(downloadData!!,list)
Log.d(TAG, "startDownload---${bundleData}")
callback?.onStartDownload(-1, bundleData)
list.forEach {
val moduleName = it.getString(KEY_MODULE_NAME)
val packData = downloadData?.getModuleData(moduleName!!)
if (packData?.status != STATUS_DOWNLOADING){
DownloadManager.get(context).prepareDownload(downloadData!!, moduleName!!)
}
}
val bundleData = buildDownloadBundle(downloadData!!,list)
Log.d(TAG, "startDownload: $bundleData")
callback?.onStartDownload(-1, bundleData)
list.forEach {
val moduleName = it.getString(KEY_MODULE_NAME)
val packData = downloadData?.getModuleData(moduleName!!)
if (packData?.status == STATUS_INITIAL_STATE){
DownloadManager.get(context).shouldStop(false)
DownloadManager.get(context).prepareDownload(downloadData!!, moduleName!!)
}
}
}

override fun getSessionStates(packageName: String?, bundle: Bundle?, callback: IAssetModuleServiceCallback?) {
Log.d(TAG, "Method (getSessionStates) called by packageName -> $packageName")
val installedAssetModuleNames = mutableListOf<String>()
bundle?.keySet()?.forEach { key ->
val value = bundle.get(key)
if (key == KEY_INSTALLED_ASSET_MODULE) {
when (value) {
is Bundle -> {
value.keySet().forEach { subKey ->
val item = value.get(subKey)
if (item is String) {
installedAssetModuleNames.add(item)
Log.d(TAG, "installed_asset_module Bundle Value: $item")
}
}
}
is ArrayList<*> -> {
value.forEachIndexed { index, item ->
if (item is Bundle) {
Log.d(TAG, "installed_asset_module Bundle at index $index")
item.keySet().forEach { subKey ->
val subItem = item.get(subKey)
if (subItem is String) {
installedAssetModuleNames.add(subItem)
Log.d(TAG, "installed_asset_module[$index] Value: $subItem")
}
}
}
}
}
else -> {
Log.d(TAG, "installed_asset_module: - ${value?.javaClass?.name}")
}
}
} else {
Log.d(TAG, "Bundle Key: $key, Value: $value")
bundle?.getParcelableArrayList<Bundle>(KEY_INSTALLED_ASSET_MODULE)?.forEach { item ->
item.keySet().forEach { subKey ->
(item.get(subKey) as? String)?.let { installedAssetModuleNames.add(it) }
}
}

Log.d(TAG, "getSessionStates installedAssetModuleNames: $installedAssetModuleNames")

if (packageName == downloadData?.packageName) {
downloadData?.moduleNames?.forEach { moduleName ->
if (installedAssetModuleNames.contains(moduleName)) { return@forEach }
Expand All @@ -179,7 +137,6 @@ class AssetModuleServiceImpl(
}
}


override fun notifyChunkTransferred(packageName: String?, bundle: Bundle?, bundle2: Bundle?, callback: IAssetModuleServiceCallback?) {
Log.d(TAG, "Method (notifyChunkTransferred) called by packageName -> $packageName")
val moduleName = bundle?.getString(KEY_MODULE_NAME)
Expand All @@ -205,16 +162,15 @@ class AssetModuleServiceImpl(
callback?.onError(Bundle().apply { putInt(KEY_ERROR_CODE, -5) })
return
}
lifecycleScope.launchWhenStarted {
Log.d(TAG, "notify: moduleName: $moduleName packNames: ${downloadData?.moduleNames}")
downloadData?.updateDownloadStatus(moduleName, STATUS_COMPLETED)
sendBroadcastForExistingFile(context, downloadData!!, moduleName, null, null)
callback?.onNotifyModuleCompleted(bundle, bundle)
}
Log.d(TAG, "notify: moduleName: $moduleName packNames: ${downloadData?.moduleNames}")
downloadData?.updateDownloadStatus(moduleName, STATUS_COMPLETED)
sendBroadcastForExistingFile(context, downloadData!!, moduleName, null, null)
callback?.onNotifyModuleCompleted(bundle, bundle)
}

override fun notifySessionFailed(packageName: String?, bundle: Bundle?, bundle2: Bundle?, callback: IAssetModuleServiceCallback?) {
Log.d(TAG, "Method (notifySessionFailed) called but not implemented by packageName -> $packageName")
callback?.onNotifySessionFailed(bundle)
}

override fun keepAlive(packageName: String?, bundle: Bundle?, callback: IAssetModuleServiceCallback?) {
Expand Down Expand Up @@ -249,27 +205,25 @@ class AssetModuleServiceImpl(
callback?.onError(Bundle().apply { putInt(KEY_ERROR_CODE, -5) })
return
}
lifecycleScope.launchWhenStarted {
if (downloadData == null || downloadData?.packageName != packageName) {
val requestedAssetModuleNames = list.map { it.getString(KEY_MODULE_NAME) }.filter { !it.isNullOrEmpty() }
val playCoreVersionCode = bundle.getInt(KEY_PLAY_CORE_VERSION_CODE)
downloadData = httpClient.initAssertModuleData(context, packageName, accountManager, requestedAssetModuleNames, playCoreVersionCode)
}
if (downloadData?.errorCode == ERROR_CODE_FAIL) {
if (moduleErrorRequested.contains(packageName)) {
callback?.onError(Bundle().apply { putInt(KEY_ERROR_CODE, -5) })
return@launchWhenStarted
}
moduleErrorRequested.add(packageName)
val result = Bundle().apply { putStringArrayList(KEY_PACK_NAMES, arrayListOf<String>()) }
callback?.onRequestDownloadInfo(result, result)
return@launchWhenStarted
if (downloadData == null || downloadData?.packageName != packageName) {
val requestedAssetModuleNames = list.map { it.getString(KEY_MODULE_NAME) }.filter { !it.isNullOrEmpty() }
val playCoreVersionCode = bundle.getInt(KEY_PLAY_CORE_VERSION_CODE)
downloadData = httpClient.initAssertModuleData(context, packageName, accountManager, requestedAssetModuleNames, playCoreVersionCode)
}
if (downloadData?.errorCode == ERROR_CODE_FAIL) {
if (moduleErrorRequested.contains(packageName)) {
callback?.onError(Bundle().apply { putInt(KEY_ERROR_CODE, -5) })
return
}
moduleErrorRequested.remove(packageName)
val bundleData = buildDownloadBundle(downloadData!!,list)
Log.d(TAG, "requestDownloadInfo---${bundleData}")
callback?.onRequestDownloadInfo(bundleData, bundleData)
moduleErrorRequested.add(packageName)
val result = Bundle().apply { putStringArrayList(KEY_PACK_NAMES, arrayListOf<String>()) }
callback?.onRequestDownloadInfo(result, result)
return
}
moduleErrorRequested.remove(packageName)
val bundleData = buildDownloadBundle(downloadData!!,list)
Log.d(TAG, "requestDownloadInfo: $bundleData")
callback?.onRequestDownloadInfo(bundleData, bundleData)
}

override fun removeModule(packageName: String?, bundle: Bundle?, bundle2: Bundle?, callback: IAssetModuleServiceCallback?) {
Expand Down
98 changes: 55 additions & 43 deletions vending-app/src/main/kotlin/com/google/android/finsky/extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import org.microg.vending.billing.GServices
import org.microg.vending.billing.core.HttpClient
import java.io.File
import java.util.Collections
import kotlinx.coroutines.runBlocking

const val STATUS_NOT_INSTALLED = 8
const val CANCELED = 6
Expand Down Expand Up @@ -90,46 +91,60 @@ fun getAppVersionCode(context: Context, packageName: String): String? {
return runCatching { context.packageManager.getPackageInfo(packageName, 0).versionCode.toString() }.getOrNull()
}

suspend fun HttpClient.initAssertModuleData(
context: Context,
packageName: String,
accountManager: AccountManager,
requestedAssetModuleNames: List<String?>,
playCoreVersionCode: Int,
fun HttpClient.initAssertModuleData(
context: Context,
packageName: String,
accountManager: AccountManager,
requestedAssetModuleNames: List<String?>,
playCoreVersionCode: Int,
): DownloadData {
Log.d(TAG, "initAssertModuleData: requestedAssetModuleNames: $requestedAssetModuleNames")
val accounts = accountManager.getAccountsByType(AuthConstants.DEFAULT_ACCOUNT_TYPE)
var oauthToken: String? = null
if (accounts.isEmpty()) {
return DownloadData(errorCode = ERROR_CODE_FAIL)
} else for (account: Account in accounts) {
oauthToken = accountManager.getAuthToken(account, AUTH_TOKEN_SCOPE, false).getString(AccountManager.KEY_AUTHTOKEN)
if (oauthToken != null) {
break
} else {
for (account: Account in accounts) {
oauthToken = runBlocking {
accountManager.getAuthToken(account, AUTH_TOKEN_SCOPE, false).getString(AccountManager.KEY_AUTHTOKEN)
}
if (oauthToken != null) {
break
}
}
}
Log.d(TAG, "initAssertModuleData: oauthToken -> $oauthToken")

if (oauthToken == null) {
return DownloadData(errorCode = ERROR_CODE_FAIL)
}
val requestPayload = AssetModuleDeliveryRequest.Builder().callerInfo(CallerInfo(getAppVersionCode(context, packageName)?.toInt())).packageName(packageName)
.playCoreVersion(playCoreVersionCode).pageSource(listOf(PageSource.UNKNOWN_SEARCH_TRAFFIC_SOURCE, PageSource.BOOKS_HOME_PAGE))
.callerState(listOf(CallerState.CALLER_APP_REQUEST, CallerState.CALLER_APP_DEBUGGABLE)).moduleInfo(ArrayList<AssetModuleInfo>().apply {
requestedAssetModuleNames.forEach { add(AssetModuleInfo.Builder().name(it).build()) }
}).build()
val androidId = GServices.getString(context.contentResolver, "android_id", "0")?.toLong()?:1
var moduleDeliveryInfo = runCatching {
post(
url = ASSET_MODULE_DELIVERY_URL,
headers = getLicenseRequestHeaders(oauthToken, androidId),
payload = requestPayload,
adapter = AssetModuleDeliveryResponse.ADAPTER
).wrapper?.deliveryInfo
}.onFailure {
Log.d(TAG, "initAssertModuleData: ", it)
}.getOrNull()

if (moduleDeliveryInfo?.status == 2) {
val requestPayload = AssetModuleDeliveryRequest.Builder()
.callerInfo(CallerInfo(getAppVersionCode(context, packageName)?.toInt()))
.packageName(packageName)
.playCoreVersion(playCoreVersionCode)
.pageSource(listOf(PageSource.UNKNOWN_SEARCH_TRAFFIC_SOURCE, PageSource.BOOKS_HOME_PAGE))
.callerState(listOf(CallerState.CALLER_APP_REQUEST, CallerState.CALLER_APP_DEBUGGABLE))
.moduleInfo(ArrayList<AssetModuleInfo>().apply {
requestedAssetModuleNames.forEach { add(AssetModuleInfo.Builder().name(it).build()) }
}).build()

val androidId = GServices.getString(context.contentResolver, "android_id", "0")?.toLong() ?: 1

var moduleDeliveryInfo = runBlocking {
runCatching {
post(
url = ASSET_MODULE_DELIVERY_URL,
headers = getLicenseRequestHeaders(oauthToken, androidId),
payload = requestPayload,
adapter = AssetModuleDeliveryResponse.ADAPTER
).wrapper?.deliveryInfo
}.getOrNull()
}

if (moduleDeliveryInfo?.status != 2) {
return initModuleDownloadInfo(context, packageName, moduleDeliveryInfo)
}

runBlocking {
runCatching {
post(
url = SYNC_NOCACHE_QOS,
Expand All @@ -138,20 +153,20 @@ suspend fun HttpClient.initAssertModuleData(
adapter = SyncResponse.ADAPTER
)
}.onFailure {
Log.d(TAG, "initAssertModuleData: sync -> ", it)
Log.d(TAG, "initAssertModuleData: ", it)
}
}

moduleDeliveryInfo = runCatching {
post(
url = ASSET_MODULE_DELIVERY_URL,
headers = getLicenseRequestHeaders(oauthToken, androidId),
payload = requestPayload,
adapter = AssetModuleDeliveryResponse.ADAPTER
).wrapper?.deliveryInfo
}.onFailure {
Log.d(TAG, "initAssertModuleData: ", it)
}.getOrNull()
moduleDeliveryInfo = runBlocking {
runCatching {
post(
url = ASSET_MODULE_DELIVERY_URL,
headers = getLicenseRequestHeaders(oauthToken, androidId),
payload = requestPayload,
adapter = AssetModuleDeliveryResponse.ADAPTER
).wrapper?.deliveryInfo
}.getOrNull()
}
Log.d(TAG, "initAssertModuleData: moduleDeliveryInfo-> $moduleDeliveryInfo")
return initModuleDownloadInfo(context, packageName, moduleDeliveryInfo)
}
Expand Down Expand Up @@ -235,11 +250,9 @@ fun buildDownloadBundle(downloadData: DownloadData, list: List<Bundle?>? = null)
totalBytesToDownload += packData.totalBytesToDownload
bytesDownloaded += packData.bytesDownloaded
}

bundleData.putStringArrayList(KEY_PACK_NAMES, arrayList)
bundleData.putLong(KEY_TOTAL_BYTES_TO_DOWNLOAD, totalBytesToDownload)
bundleData.putLong(KEY_BYTES_DOWNLOADED, bytesDownloaded)

return bundleData
}

Expand Down Expand Up @@ -300,7 +313,6 @@ fun sendBroadcastForExistingFile(context: Context, downloadData: DownloadData, m
downloadBundle.putString(combineModule(KEY_UNCOMPRESSED_HASH_SHA256, moduleName, chunkName), uncompressedHashSha256)
}
downloadBundle.putStringArrayList(combineModule(KEY_SLICE_IDS, moduleName), packData.listOfSubcontractNames)
Log.d(TAG, "sendBroadcastForExistingFile: $downloadBundle")
sendBroadCast(context, downloadData, downloadBundle)
} catch (e: Exception) {
Log.w(TAG, "sendBroadcastForExistingFile error:" + e.message)
Expand Down

0 comments on commit 71a8f59

Please sign in to comment.