@@ -56,22 +56,32 @@ class AssetModuleServiceImpl(
5656 private val packageDownloadData : MutableMap <String , DownloadData ?>
5757) : AbstractAssetModuleServiceImpl(context, lifecycle) {
5858 private val fileDescriptorMap = mutableMapOf<File , ParcelFileDescriptor >()
59+ private val lock = Any ()
5960
6061 private fun checkSessionValid (packageName : String , sessionId : Int ) {
62+ Log .d(TAG , " checkSessionValid: $packageName $sessionId ${packageDownloadData[packageName]?.sessionIds} " )
6163 if (packageDownloadData[packageName]?.sessionIds?.values?.contains(sessionId) != true ) {
6264 Log .w(TAG , " No active session with id $sessionId in $packageName " )
6365 throw AssetPackException (AssetPackErrorCode .ACCESS_DENIED )
6466 }
6567 }
6668
67- override fun getDefaultSessionId (packageName : String , moduleName : String ): Int =
69+ override fun getDefaultSessionId (packageName : String , moduleName : String ): Int = synchronized(lock) {
6870 packageDownloadData[packageName]?.sessionIds?.get(moduleName) ? : 0
71+ }
6972
7073 override suspend fun startDownload (params : StartDownloadParameters , packageName : String , callback : IAssetModuleServiceCallback ? ) {
71- if (packageDownloadData[packageName] == null ||
72- packageDownloadData[packageName]?.packageName != packageName ||
73- packageDownloadData[packageName]?.moduleNames?.intersect(params.moduleNames.toSet())?.isEmpty() == true ) {
74- packageDownloadData[packageName] = httpClient.initAssetModuleData(context, packageName, accountManager, params.moduleNames, params.options)
74+ val needInit = synchronized(lock) {
75+ packageDownloadData[packageName] == null ||
76+ packageDownloadData[packageName]?.packageName != packageName ||
77+ packageDownloadData[packageName]?.moduleNames?.intersect(params.moduleNames.toSet())?.isEmpty() == true
78+ }
79+
80+ if (needInit) {
81+ val newData = httpClient.initAssetModuleData(context, packageName, accountManager, params.moduleNames, params.options)
82+ synchronized(lock) {
83+ packageDownloadData[packageName] = packageDownloadData[packageName].merge(newData)
84+ }
7585 if (packageDownloadData[packageName] == null ) {
7686 throw AssetPackException (AssetPackErrorCode .API_NOT_AVAILABLE )
7787 }
@@ -114,24 +124,26 @@ class AssetModuleServiceImpl(
114124 override suspend fun getSessionStates (params : GetSessionStatesParameters , packageName : String , callback : IAssetModuleServiceCallback ? ) {
115125 val listBundleData: MutableList <Bundle > = mutableListOf ()
116126
117- if (packageDownloadData[packageName] != null && packageDownloadData[packageName]?.moduleNames?.all {
118- packageDownloadData[packageName]?.getModuleData(it)?.status == AssetPackStatus .COMPLETED
119- } == true && params.installedAssetModules.isEmpty()) {
120- Log .d(TAG , " getSessionStates: resetAllModuleStatus: $listBundleData " )
121- packageDownloadData[packageName]?.resetAllModuleStatus()
122- callback?.onGetSessionStates(listBundleData)
123- return
124- }
127+ synchronized(lock) {
128+ if (packageDownloadData[packageName] != null && packageDownloadData[packageName]?.moduleNames?.all {
129+ packageDownloadData[packageName]?.getModuleData(it)?.status == AssetPackStatus .COMPLETED
130+ } == true && params.installedAssetModules.isEmpty()) {
131+ Log .d(TAG , " getSessionStates: resetAllModuleStatus: $listBundleData " )
132+ packageDownloadData[packageName]?.resetAllModuleStatus()
133+ callback?.onGetSessionStates(listBundleData)
134+ return
135+ }
125136
126- packageDownloadData[packageName]?.moduleNames?.forEach { moduleName ->
127- if (moduleName in params.installedAssetModules) return @forEach
137+ packageDownloadData[packageName]?.moduleNames?.forEach { moduleName ->
138+ if (moduleName in params.installedAssetModules) return @forEach
128139
129- listBundleData.add(sendBroadcastForExistingFile(context, packageDownloadData[packageName]!! , moduleName, null , null ))
140+ listBundleData.add(sendBroadcastForExistingFile(context, packageDownloadData[packageName]!! , moduleName, null , null ))
130141
131- packageDownloadData[packageName]?.getModuleData(moduleName)?.chunks?.forEach { chunkData ->
132- val destination = chunkData.getChunkFile(context)
133- if (destination.exists() && destination.length() == chunkData.chunkBytesToDownload) {
134- sendBroadcastForExistingFile(context, packageDownloadData[packageName]!! , moduleName, chunkData, destination)
142+ packageDownloadData[packageName]?.getModuleData(moduleName)?.chunks?.forEach { chunkData ->
143+ val destination = chunkData.getChunkFile(context)
144+ if (destination.exists() && destination.length() == chunkData.chunkBytesToDownload) {
145+ sendBroadcastForExistingFile(context, packageDownloadData[packageName]!! , moduleName, chunkData, destination)
146+ }
135147 }
136148 }
137149 }
@@ -143,9 +155,11 @@ class AssetModuleServiceImpl(
143155 override suspend fun notifyChunkTransferred (params : NotifyChunkTransferredParameters , packageName : String , callback : IAssetModuleServiceCallback ? ) {
144156 checkSessionValid(packageName, params.sessionId)
145157
146- val downLoadFile = context.getChunkFile(params.sessionId, params.moduleName, params.sliceId, params.chunkNumber)
147- fileDescriptorMap[downLoadFile]?.close()
148- fileDescriptorMap.remove(downLoadFile)
158+ synchronized(lock) {
159+ val downLoadFile = context.getChunkFile(params.sessionId, params.moduleName, params.sliceId, params.chunkNumber)
160+ fileDescriptorMap[downLoadFile]?.close()
161+ fileDescriptorMap.remove(downLoadFile)
162+ }
149163 // TODO: Remove chunk after successful transfer of chunk or only with module?
150164 callback?.onNotifyChunkTransferred(
151165 bundleOf(BundleKeys .MODULE_NAME to params.moduleName) +
@@ -159,8 +173,10 @@ class AssetModuleServiceImpl(
159173 override suspend fun notifyModuleCompleted (params : NotifyModuleCompletedParameters , packageName : String , callback : IAssetModuleServiceCallback ? ) {
160174 checkSessionValid(packageName, params.sessionId)
161175
162- packageDownloadData[packageName]?.updateDownloadStatus(params.moduleName, AssetPackStatus .COMPLETED )
163- sendBroadcastForExistingFile(context, packageDownloadData[packageName]!! , params.moduleName, null , null )
176+ synchronized(lock) {
177+ packageDownloadData[packageName]?.updateDownloadStatus(params.moduleName, AssetPackStatus .COMPLETED )
178+ sendBroadcastForExistingFile(context, packageDownloadData[packageName]!! , params.moduleName, null , null )
179+ }
164180
165181 val directory = context.getModuleDir(params.sessionId, params.moduleName)
166182 if (directory.exists()) {
@@ -192,9 +208,11 @@ class AssetModuleServiceImpl(
192208 override suspend fun getChunkFileDescriptor (params : GetChunkFileDescriptorParameters , packageName : String , callback : IAssetModuleServiceCallback ? ) {
193209 checkSessionValid(packageName, params.sessionId)
194210
195- val downLoadFile = context.getChunkFile(params.sessionId, params.moduleName, params.sliceId, params.chunkNumber)
196- val parcelFileDescriptor = ParcelFileDescriptor .open(downLoadFile, ParcelFileDescriptor .MODE_READ_ONLY ).also {
197- fileDescriptorMap[downLoadFile] = it
211+ val parcelFileDescriptor = synchronized(lock) {
212+ val downLoadFile = context.getChunkFile(params.sessionId, params.moduleName, params.sliceId, params.chunkNumber)
213+ ParcelFileDescriptor .open(downLoadFile, ParcelFileDescriptor .MODE_READ_ONLY ).also {
214+ fileDescriptorMap[downLoadFile] = it
215+ }
198216 }
199217
200218 Log .d(TAG , " getChunkFileDescriptor -> $parcelFileDescriptor " )
@@ -205,10 +223,17 @@ class AssetModuleServiceImpl(
205223 }
206224
207225 override suspend fun requestDownloadInfo (params : RequestDownloadInfoParameters , packageName : String , callback : IAssetModuleServiceCallback ? ) {
208- if (packageDownloadData[packageName] == null ||
209- packageDownloadData[packageName]?.packageName != packageName ||
210- packageDownloadData[packageName]?.moduleNames?.intersect(params.moduleNames.toSet())?.isEmpty() == true ) {
211- packageDownloadData[packageName] = httpClient.initAssetModuleData(context, packageName, accountManager, params.moduleNames, params.options)
226+ val needInit = synchronized(lock) {
227+ packageDownloadData[packageName] == null ||
228+ packageDownloadData[packageName]?.packageName != packageName ||
229+ packageDownloadData[packageName]?.moduleNames?.intersect(params.moduleNames.toSet())?.isEmpty() == true
230+ }
231+
232+ if (needInit) {
233+ val newData = httpClient.initAssetModuleData(context, packageName, accountManager, params.moduleNames, params.options)
234+ synchronized(lock) {
235+ packageDownloadData[packageName] = packageDownloadData[packageName].merge(newData)
236+ }
212237 if (packageDownloadData[packageName] == null ) {
213238 throw AssetPackException (AssetPackErrorCode .API_NOT_AVAILABLE )
214239 }
0 commit comments