1264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu/* 2264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu * Copyright (C) 2017 The Android Open Source Project 3264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu * 4264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu * Licensed under the Apache License, Version 2.0 (the "License"); 5264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu * you may not use this file except in compliance with the License. 6264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu * You may obtain a copy of the License at 7264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu * 8264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu * http://www.apache.org/licenses/LICENSE-2.0 9264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu * 10264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu * Unless required by applicable law or agreed to in writing, software 11264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu * distributed under the License is distributed on an "AS IS" BASIS, 12264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu * See the License for the specific language governing permissions and 14264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu * limitations under the License 15264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu */ 16264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 17264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liupackage com.android.phone.testapps.embmsmw; 18264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 19264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.app.Activity; 20264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.app.Service; 21264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.content.BroadcastReceiver; 22264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.content.ComponentName; 23264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.content.Context; 24264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.content.Intent; 25264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.net.Uri; 26264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.os.Binder; 27264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.os.Bundle; 28264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.os.Handler; 29264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.os.HandlerThread; 30264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.os.IBinder; 31264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.os.ParcelFileDescriptor; 32eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liuimport android.os.RemoteException; 33d625298cd6d828d59ea41df2b6be24d0c44150b9Hall Liuimport android.telephony.MbmsDownloadSession; 34264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.telephony.mbms.DownloadRequest; 35de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebingerimport android.telephony.mbms.DownloadStateCallback; 36eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liuimport android.telephony.mbms.FileInfo; 37eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liuimport android.telephony.mbms.FileServiceInfo; 38d625298cd6d828d59ea41df2b6be24d0c44150b9Hall Liuimport android.telephony.mbms.MbmsDownloadSessionCallback; 396f37f0cc96e5b28ef9d60a5b17fd2e8b008c39c0Hall Liuimport android.telephony.mbms.MbmsErrors; 40264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.telephony.mbms.UriPathPair; 41264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.telephony.mbms.vendor.IMbmsDownloadService; 42264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.telephony.mbms.vendor.MbmsDownloadServiceBase; 43c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liuimport android.telephony.mbms.vendor.VendorUtils; 44264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport android.util.Log; 45264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 46264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport java.io.IOException; 47264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport java.io.InputStream; 48264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport java.io.OutputStream; 49264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport java.util.ArrayList; 50264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport java.util.Arrays; 51434fb4c1f2796b91b79c5a6646518305487802abHall Liuimport java.util.Collections; 52eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liuimport java.util.HashMap; 53eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liuimport java.util.HashSet; 54264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liuimport java.util.List; 55eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liuimport java.util.Map; 56eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liuimport java.util.Set; 57eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liuimport java.util.concurrent.ConcurrentHashMap; 58264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 59264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liupublic class EmbmsSampleDownloadService extends Service { 60eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu private static final Set<String> ALLOWED_PACKAGES = new HashSet<String>() {{ 61eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu add("com.android.phone.testapps.embmsdownload"); 62eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu }}; 63eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu 64264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu private static final String LOG_TAG = "EmbmsSampleDownload"; 6547f9e74cbb51427c9d1c8a47d414b7976a7d554cHall Liu private static final long INITIALIZATION_DELAY = 200; 66eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu private static final long SEND_FILE_SERVICE_INFO_DELAY = 500; 67264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu private static final long DOWNLOAD_DELAY_MS = 1000; 68eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu private static final long FILE_SEPARATION_DELAY = 500; 69264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 70264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu private final IMbmsDownloadService mBinder = new MbmsDownloadServiceBase() { 71264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu @Override 72d625298cd6d828d59ea41df2b6be24d0c44150b9Hall Liu public int initialize(int subId, MbmsDownloadSessionCallback callback) { 7347f9e74cbb51427c9d1c8a47d414b7976a7d554cHall Liu int packageUid = Binder.getCallingUid(); 7447f9e74cbb51427c9d1c8a47d414b7976a7d554cHall Liu String[] packageNames = getPackageManager().getPackagesForUid(packageUid); 75264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu if (packageNames == null) { 766f37f0cc96e5b28ef9d60a5b17fd2e8b008c39c0Hall Liu return MbmsErrors.InitializationErrors.ERROR_APP_PERMISSIONS_NOT_GRANTED; 77264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu } 78eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu boolean isUidAllowed = Arrays.stream(packageNames).anyMatch(ALLOWED_PACKAGES::contains); 79eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu if (!isUidAllowed) { 806f37f0cc96e5b28ef9d60a5b17fd2e8b008c39c0Hall Liu return MbmsErrors.InitializationErrors.ERROR_APP_PERMISSIONS_NOT_GRANTED; 81eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu } 82264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 8347f9e74cbb51427c9d1c8a47d414b7976a7d554cHall Liu // Do initialization with a bit of a delay to simulate work being done. 8447f9e74cbb51427c9d1c8a47d414b7976a7d554cHall Liu mHandler.postDelayed(() -> { 851b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu FrontendAppIdentifier appKey = new FrontendAppIdentifier(packageUid, subId); 8647f9e74cbb51427c9d1c8a47d414b7976a7d554cHall Liu if (!mAppCallbacks.containsKey(appKey)) { 87779ff5fab7677f6ac5ac20db93a906d38a20ebcaHall Liu mAppCallbacks.put(appKey, callback); 88c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu ComponentName appReceiver = VendorUtils.getAppReceiverFromPackageName( 89c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu EmbmsSampleDownloadService.this, 90c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu getPackageManager().getNameForUid(packageUid)); 9147f9e74cbb51427c9d1c8a47d414b7976a7d554cHall Liu mAppReceivers.put(appKey, appReceiver); 9247f9e74cbb51427c9d1c8a47d414b7976a7d554cHall Liu } else { 9380d0d75521fa8d539bbb5afb506b1e632dfdab7dHall Liu callback.onError( 946f37f0cc96e5b28ef9d60a5b17fd2e8b008c39c0Hall Liu MbmsErrors.InitializationErrors.ERROR_DUPLICATE_INITIALIZE, ""); 9547f9e74cbb51427c9d1c8a47d414b7976a7d554cHall Liu return; 9647f9e74cbb51427c9d1c8a47d414b7976a7d554cHall Liu } 9780d0d75521fa8d539bbb5afb506b1e632dfdab7dHall Liu callback.onMiddlewareReady(); 9847f9e74cbb51427c9d1c8a47d414b7976a7d554cHall Liu }, INITIALIZATION_DELAY); 99b17262ce28a4fbd64e6209b7d0c64305785d499eHall Liu 1006f37f0cc96e5b28ef9d60a5b17fd2e8b008c39c0Hall Liu return MbmsErrors.SUCCESS; 101eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu } 102eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu 103eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu @Override 104d625298cd6d828d59ea41df2b6be24d0c44150b9Hall Liu public int requestUpdateFileServices(int subscriptionId, 105eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu List<String> serviceClasses) throws RemoteException { 106eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu FrontendAppIdentifier appKey = 1071b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu new FrontendAppIdentifier(Binder.getCallingUid(), subscriptionId); 108eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu checkInitialized(appKey); 109eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu 110eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu List<FileServiceInfo> serviceInfos = 111eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu FileServiceRepository.getInstance(EmbmsSampleDownloadService.this) 112eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu .getFileServicesForClasses(serviceClasses); 113eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu 114eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu mHandler.postDelayed(() -> { 115d625298cd6d828d59ea41df2b6be24d0c44150b9Hall Liu MbmsDownloadSessionCallback appCallback = mAppCallbacks.get(appKey); 11680d0d75521fa8d539bbb5afb506b1e632dfdab7dHall Liu appCallback.onFileServicesUpdated(serviceInfos); 117eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu }, SEND_FILE_SERVICE_INFO_DELAY); 1186f37f0cc96e5b28ef9d60a5b17fd2e8b008c39c0Hall Liu return MbmsErrors.SUCCESS; 119eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu } 120eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu 121eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu @Override 1221b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu public int setTempFileRootDirectory(int subscriptionId, 123eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu String rootDirectoryPath) throws RemoteException { 124eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu FrontendAppIdentifier appKey = 1251b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu new FrontendAppIdentifier(Binder.getCallingUid(), subscriptionId); 126eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu checkInitialized(appKey); 127eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu 1281b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu if (mActiveDownloadRequests.getOrDefault(appKey, Collections.emptySet()).size() > 0) { 1296f37f0cc96e5b28ef9d60a5b17fd2e8b008c39c0Hall Liu return MbmsErrors.DownloadErrors.ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT; 130eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu } 131eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu mAppTempFileRoots.put(appKey, rootDirectoryPath); 1326f37f0cc96e5b28ef9d60a5b17fd2e8b008c39c0Hall Liu return MbmsErrors.SUCCESS; 133eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu } 134264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 135eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu @Override 136d625298cd6d828d59ea41df2b6be24d0c44150b9Hall Liu public int download(DownloadRequest downloadRequest) { 137eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu FrontendAppIdentifier appKey = new FrontendAppIdentifier( 1381b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu Binder.getCallingUid(), downloadRequest.getSubscriptionId()); 139eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu checkInitialized(appKey); 140264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 141eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu mHandler.post(() -> sendFdRequest(downloadRequest, appKey)); 1426f37f0cc96e5b28ef9d60a5b17fd2e8b008c39c0Hall Liu return MbmsErrors.SUCCESS; 143264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu } 1441b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu 1451b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu @Override 146de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger public int registerStateCallback(DownloadRequest downloadRequest, 147de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger DownloadStateCallback callback) throws RemoteException { 148de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger mDownloadStateCallbacks.put(downloadRequest, callback); 149de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger return MbmsErrors.SUCCESS; 150de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger } 151de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger 152de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger @Override 1531b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu public int cancelDownload(DownloadRequest downloadRequest) { 1541b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu FrontendAppIdentifier appKey = new FrontendAppIdentifier( 1551b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu Binder.getCallingUid(), downloadRequest.getSubscriptionId()); 1561b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu checkInitialized(appKey); 1571b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu if (!mActiveDownloadRequests.getOrDefault( 1581b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu appKey, Collections.emptySet()).contains(downloadRequest)) { 1596f37f0cc96e5b28ef9d60a5b17fd2e8b008c39c0Hall Liu return MbmsErrors.DownloadErrors.ERROR_UNKNOWN_DOWNLOAD_REQUEST; 1601b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu } 1611b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu mActiveDownloadRequests.get(appKey).remove(downloadRequest); 1626f37f0cc96e5b28ef9d60a5b17fd2e8b008c39c0Hall Liu return MbmsErrors.SUCCESS; 1631b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu } 16480d0d75521fa8d539bbb5afb506b1e632dfdab7dHall Liu 16580d0d75521fa8d539bbb5afb506b1e632dfdab7dHall Liu @Override 16680d0d75521fa8d539bbb5afb506b1e632dfdab7dHall Liu public void onAppCallbackDied(int uid, int subscriptionId) { 16780d0d75521fa8d539bbb5afb506b1e632dfdab7dHall Liu FrontendAppIdentifier appKey = new FrontendAppIdentifier(uid, subscriptionId); 16880d0d75521fa8d539bbb5afb506b1e632dfdab7dHall Liu 16980d0d75521fa8d539bbb5afb506b1e632dfdab7dHall Liu Log.i(LOG_TAG, "Disposing app " + appKey + " due to binder death"); 17080d0d75521fa8d539bbb5afb506b1e632dfdab7dHall Liu mAppCallbacks.remove(appKey); 17180d0d75521fa8d539bbb5afb506b1e632dfdab7dHall Liu // TODO: call dispose 17280d0d75521fa8d539bbb5afb506b1e632dfdab7dHall Liu } 173264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu }; 174264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 175434fb4c1f2796b91b79c5a6646518305487802abHall Liu private static EmbmsSampleDownloadService sInstance = null; 176434fb4c1f2796b91b79c5a6646518305487802abHall Liu 177d625298cd6d828d59ea41df2b6be24d0c44150b9Hall Liu private final Map<FrontendAppIdentifier, MbmsDownloadSessionCallback> mAppCallbacks = 178eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu new HashMap<>(); 179eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu private final Map<FrontendAppIdentifier, ComponentName> mAppReceivers = new HashMap<>(); 180eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu private final Map<FrontendAppIdentifier, String> mAppTempFileRoots = new HashMap<>(); 1811b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu private final Map<FrontendAppIdentifier, Set<DownloadRequest>> mActiveDownloadRequests = 182eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu new ConcurrentHashMap<>(); 183434fb4c1f2796b91b79c5a6646518305487802abHall Liu // A map of app-identifiers to (maps of service-ids to sets of temp file uris in use) 184434fb4c1f2796b91b79c5a6646518305487802abHall Liu private final Map<FrontendAppIdentifier, Map<String, Set<Uri>>> mTempFilesInUse = 185434fb4c1f2796b91b79c5a6646518305487802abHall Liu new ConcurrentHashMap<>(); 186de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger private final Map<DownloadRequest, DownloadStateCallback> mDownloadStateCallbacks = 187de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger new ConcurrentHashMap<>(); 188eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu 189264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu private HandlerThread mHandlerThread; 190264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu private Handler mHandler; 191434fb4c1f2796b91b79c5a6646518305487802abHall Liu private int mDownloadDelayFactor = 1; 192264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 193264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu @Override 194264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu public IBinder onBind(Intent intent) { 195264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu mHandlerThread = new HandlerThread("EmbmsTestDownloadServiceWorker"); 196264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu mHandlerThread.start(); 197264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu mHandler = new Handler(mHandlerThread.getLooper()); 198434fb4c1f2796b91b79c5a6646518305487802abHall Liu sInstance = this; 199264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu return mBinder.asBinder(); 200264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu } 201264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 202434fb4c1f2796b91b79c5a6646518305487802abHall Liu public static EmbmsSampleDownloadService getInstance() { 203434fb4c1f2796b91b79c5a6646518305487802abHall Liu return sInstance; 204434fb4c1f2796b91b79c5a6646518305487802abHall Liu } 205434fb4c1f2796b91b79c5a6646518305487802abHall Liu 206434fb4c1f2796b91b79c5a6646518305487802abHall Liu public void requestCleanup() { 207434fb4c1f2796b91b79c5a6646518305487802abHall Liu // Assume that there's only one app, and do it for all the services. 208434fb4c1f2796b91b79c5a6646518305487802abHall Liu FrontendAppIdentifier registeredAppId = mAppReceivers.keySet().iterator().next(); 209434fb4c1f2796b91b79c5a6646518305487802abHall Liu ComponentName appReceiver = mAppReceivers.values().iterator().next(); 210434fb4c1f2796b91b79c5a6646518305487802abHall Liu for (FileServiceInfo fileServiceInfo : 211434fb4c1f2796b91b79c5a6646518305487802abHall Liu FileServiceRepository.getInstance(this).getAllFileServices()) { 212c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu Intent cleanupIntent = new Intent(VendorUtils.ACTION_CLEANUP); 213434fb4c1f2796b91b79c5a6646518305487802abHall Liu cleanupIntent.setComponent(appReceiver); 2147662a90beac0aa6af9dbe96276826a5c8e7f39e4Hall Liu cleanupIntent.putExtra(VendorUtils.EXTRA_SERVICE_ID, fileServiceInfo.getServiceId()); 215c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu cleanupIntent.putExtra(VendorUtils.EXTRA_TEMP_FILE_ROOT, 216434fb4c1f2796b91b79c5a6646518305487802abHall Liu mAppTempFileRoots.get(registeredAppId)); 217434fb4c1f2796b91b79c5a6646518305487802abHall Liu Set<Uri> tempFilesInUse = 218434fb4c1f2796b91b79c5a6646518305487802abHall Liu mTempFilesInUse.getOrDefault(registeredAppId, Collections.emptyMap()) 219434fb4c1f2796b91b79c5a6646518305487802abHall Liu .getOrDefault(fileServiceInfo.getServiceId(), Collections.emptySet()); 220c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu cleanupIntent.putExtra(VendorUtils.EXTRA_TEMP_FILES_IN_USE, 221434fb4c1f2796b91b79c5a6646518305487802abHall Liu new ArrayList<>(tempFilesInUse)); 222434fb4c1f2796b91b79c5a6646518305487802abHall Liu sendBroadcast(cleanupIntent); 223434fb4c1f2796b91b79c5a6646518305487802abHall Liu } 224434fb4c1f2796b91b79c5a6646518305487802abHall Liu } 225434fb4c1f2796b91b79c5a6646518305487802abHall Liu 226434fb4c1f2796b91b79c5a6646518305487802abHall Liu public void requestExtraTempFiles(FileServiceInfo serviceInfo) { 227434fb4c1f2796b91b79c5a6646518305487802abHall Liu // Assume one app, and do it for the specified service. 228434fb4c1f2796b91b79c5a6646518305487802abHall Liu FrontendAppIdentifier registeredAppId = mAppReceivers.keySet().iterator().next(); 229434fb4c1f2796b91b79c5a6646518305487802abHall Liu ComponentName appReceiver = mAppReceivers.values().iterator().next(); 230c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu Intent fdRequestIntent = new Intent(VendorUtils.ACTION_FILE_DESCRIPTOR_REQUEST); 2317662a90beac0aa6af9dbe96276826a5c8e7f39e4Hall Liu fdRequestIntent.putExtra(VendorUtils.EXTRA_SERVICE_ID, serviceInfo.getServiceId()); 232c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu fdRequestIntent.putExtra(VendorUtils.EXTRA_FD_COUNT, 10); 233c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu fdRequestIntent.putExtra(VendorUtils.EXTRA_TEMP_FILE_ROOT, 234434fb4c1f2796b91b79c5a6646518305487802abHall Liu mAppTempFileRoots.get(registeredAppId)); 235434fb4c1f2796b91b79c5a6646518305487802abHall Liu fdRequestIntent.setComponent(appReceiver); 236434fb4c1f2796b91b79c5a6646518305487802abHall Liu 237434fb4c1f2796b91b79c5a6646518305487802abHall Liu sendOrderedBroadcast(fdRequestIntent, 238434fb4c1f2796b91b79c5a6646518305487802abHall Liu null, // receiverPermission 239434fb4c1f2796b91b79c5a6646518305487802abHall Liu new BroadcastReceiver() { 240434fb4c1f2796b91b79c5a6646518305487802abHall Liu @Override 241434fb4c1f2796b91b79c5a6646518305487802abHall Liu public void onReceive(Context context, Intent intent) { 242434fb4c1f2796b91b79c5a6646518305487802abHall Liu int result = getResultCode(); 243434fb4c1f2796b91b79c5a6646518305487802abHall Liu Bundle extras = getResultExtras(false); 244434fb4c1f2796b91b79c5a6646518305487802abHall Liu Log.i(LOG_TAG, "Received extra temp files. Result " + result); 245434fb4c1f2796b91b79c5a6646518305487802abHall Liu if (extras != null) { 246434fb4c1f2796b91b79c5a6646518305487802abHall Liu Log.i(LOG_TAG, "Got " 247434fb4c1f2796b91b79c5a6646518305487802abHall Liu + extras.getParcelableArrayList( 248c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu VendorUtils.EXTRA_FREE_URI_LIST).size() 249434fb4c1f2796b91b79c5a6646518305487802abHall Liu + " fds"); 250434fb4c1f2796b91b79c5a6646518305487802abHall Liu } 251434fb4c1f2796b91b79c5a6646518305487802abHall Liu } 252434fb4c1f2796b91b79c5a6646518305487802abHall Liu }, 253434fb4c1f2796b91b79c5a6646518305487802abHall Liu null, // scheduler 254434fb4c1f2796b91b79c5a6646518305487802abHall Liu Activity.RESULT_OK, 255434fb4c1f2796b91b79c5a6646518305487802abHall Liu null, // initialData 256434fb4c1f2796b91b79c5a6646518305487802abHall Liu null /* initialExtras */); 257434fb4c1f2796b91b79c5a6646518305487802abHall Liu } 258434fb4c1f2796b91b79c5a6646518305487802abHall Liu 259434fb4c1f2796b91b79c5a6646518305487802abHall Liu public void delayDownloads(int factor) { 260434fb4c1f2796b91b79c5a6646518305487802abHall Liu mDownloadDelayFactor = factor; 261434fb4c1f2796b91b79c5a6646518305487802abHall Liu } 262434fb4c1f2796b91b79c5a6646518305487802abHall Liu 263eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu private void sendFdRequest(DownloadRequest request, FrontendAppIdentifier appKey) { 264eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu int numFds = getNumFdsNeededForRequest(request); 265264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu // Compose the FILE_DESCRIPTOR_REQUEST_INTENT 266c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu Intent requestIntent = new Intent(VendorUtils.ACTION_FILE_DESCRIPTOR_REQUEST); 2677662a90beac0aa6af9dbe96276826a5c8e7f39e4Hall Liu requestIntent.putExtra(VendorUtils.EXTRA_SERVICE_ID, request.getFileServiceId()); 268c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu requestIntent.putExtra(VendorUtils.EXTRA_FD_COUNT, numFds); 269c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu requestIntent.putExtra(VendorUtils.EXTRA_TEMP_FILE_ROOT, 270eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu mAppTempFileRoots.get(appKey)); 271eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu requestIntent.setComponent(mAppReceivers.get(appKey)); 272264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 273264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu // Send as an ordered broadcast, using a BroadcastReceiver to capture the result 274264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu // containing UriPathPairs. 275264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu sendOrderedBroadcast(requestIntent, 276264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu null, // receiverPermission 277264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu new BroadcastReceiver() { 278264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu @Override 279264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu public void onReceive(Context context, Intent intent) { 280264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu Bundle resultExtras = getResultExtras(false); 281264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu // This delay is to emulate the time it'd usually take to fetch the file 282264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu // off the network. 283264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu mHandler.postDelayed( 284eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu () -> performDownload(request, appKey, resultExtras), 285264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu DOWNLOAD_DELAY_MS); 286264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu } 287264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu }, 288264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu null, // scheduler 289264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu Activity.RESULT_OK, 290264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu null, // initialData 291264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu null /* initialExtras */); 292264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu } 293264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 294eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu private void performDownload(DownloadRequest request, FrontendAppIdentifier appKey, 295eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu Bundle extras) { 296264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu List<UriPathPair> tempFiles = extras.getParcelableArrayList( 297c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu VendorUtils.EXTRA_FREE_URI_LIST); 298d2860c33f4b1854fcfb13f2247c0e004463d034fHall Liu List<FileInfo> filesToDownload = FileServiceRepository.getInstance(this) 299d2860c33f4b1854fcfb13f2247c0e004463d034fHall Liu .getFileServiceInfoForId(request.getFileServiceId()) 300d2860c33f4b1854fcfb13f2247c0e004463d034fHall Liu .getFiles(); 301264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 302eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu if (tempFiles.size() != filesToDownload.size()) { 303eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu Log.w(LOG_TAG, "Different numbers of temp files and files to download..."); 304eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu } 305eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu 3061b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu if (!mActiveDownloadRequests.containsKey(appKey)) { 3071b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu mActiveDownloadRequests.put(appKey, Collections.synchronizedSet(new HashSet<>())); 3081b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu } 3091b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu mActiveDownloadRequests.get(appKey).add(request); 3101b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu 311eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu // Go through the files one-by-one and send them to the frontend app with a delay between 312eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu // each one. 313eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu for (int i = 0; i < tempFiles.size(); i++) { 314eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu if (i >= filesToDownload.size()) { 315eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu break; 316eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu } 317eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu UriPathPair tempFile = tempFiles.get(i); 318d2860c33f4b1854fcfb13f2247c0e004463d034fHall Liu addTempFileInUse(appKey, request.getFileServiceId(), 319434fb4c1f2796b91b79c5a6646518305487802abHall Liu tempFile.getFilePathUri()); 320eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu FileInfo fileToDownload = filesToDownload.get(i); 321eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu mHandler.postDelayed(() -> { 3221b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu if (mActiveDownloadRequests.get(appKey) == null || 3231b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu !mActiveDownloadRequests.get(appKey).contains(request)) { 3241b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu return; 3251b74eafe40bbe7480e4ad65dffd851b49455d2b9Hall Liu } 326eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu downloadSingleFile(appKey, request, tempFile, fileToDownload); 327d2860c33f4b1854fcfb13f2247c0e004463d034fHall Liu removeTempFileInUse(appKey, request.getFileServiceId(), 328434fb4c1f2796b91b79c5a6646518305487802abHall Liu tempFile.getFilePathUri()); 329434fb4c1f2796b91b79c5a6646518305487802abHall Liu }, FILE_SEPARATION_DELAY * i * mDownloadDelayFactor); 330eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu } 331eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu } 332eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu 333eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu private void downloadSingleFile(FrontendAppIdentifier appKey, DownloadRequest request, 334eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu UriPathPair tempFile, FileInfo fileToDownload) { 335d625298cd6d828d59ea41df2b6be24d0c44150b9Hall Liu int result = MbmsDownloadSession.RESULT_SUCCESSFUL; 336de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger // Test Callback 337de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger DownloadStateCallback c = mDownloadStateCallbacks.get(request); 338de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger if (c != null) { 339de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger c.onProgressUpdated(request, fileToDownload, 0, 10, 0, 10); 340de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger } 341de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger // Test Callback 342de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger if (c != null) { 343de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger c.onStateUpdated(request, fileToDownload, 344de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger MbmsDownloadSession.STATUS_ACTIVELY_DOWNLOADING); 345de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger } 346264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu try { 347264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu // Get the ParcelFileDescriptor for the single temp file we requested 348eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu ParcelFileDescriptor tempFileFd = getContentResolver().openFileDescriptor( 349eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu tempFile.getContentUri(), "rw"); 350264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu OutputStream destinationStream = 351eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu new ParcelFileDescriptor.AutoCloseOutputStream(tempFileFd); 352264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 353264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu // This is how you get the native fd 354eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu Log.i(LOG_TAG, "Native fd: " + tempFileFd.getFd()); 355264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 356eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu int resourceId = FileServiceRepository.getInstance(this) 357eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu .getResourceForFileUri(fileToDownload.getUri()); 358264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu // Open the picture we have in our res/raw directory 359eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu InputStream image = getResources().openRawResource(resourceId); 360264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 361264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu // Copy it into the temp file in the app's file space (crudely) 362264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu byte[] imageBuffer = new byte[image.available()]; 363264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu image.read(imageBuffer); 364264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu destinationStream.write(imageBuffer); 365264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu destinationStream.flush(); 366264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu } catch (IOException e) { 367d625298cd6d828d59ea41df2b6be24d0c44150b9Hall Liu result = MbmsDownloadSession.RESULT_CANCELLED; 368264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu } 369de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger // Test Callback 370de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger if (c != null) { 371de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger c.onProgressUpdated(request, fileToDownload, 10, 10, 10, 10); 372de2c90206b0eb691160731ea2f54b8344d2483f9Brad Ebinger } 373d2860c33f4b1854fcfb13f2247c0e004463d034fHall Liu // Take a round-trip through the download request serialization to exercise it 37408aa7e2f8478d4adbe9e5bfee6a76be8ee6bed6aBrad Ebinger DownloadRequest request1 = new DownloadRequest.Builder(request.getSourceUri()) 375d2860c33f4b1854fcfb13f2247c0e004463d034fHall Liu .setSubscriptionId(request.getSubscriptionId()) 376d2860c33f4b1854fcfb13f2247c0e004463d034fHall Liu .setServiceId(request.getFileServiceId()) 377d2860c33f4b1854fcfb13f2247c0e004463d034fHall Liu .setOpaqueData(request.getOpaqueData()) 378d2860c33f4b1854fcfb13f2247c0e004463d034fHall Liu .build(); 379d2860c33f4b1854fcfb13f2247c0e004463d034fHall Liu 380264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu Intent downloadResultIntent = 381c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu new Intent(VendorUtils.ACTION_DOWNLOAD_RESULT_INTERNAL); 3826f37f0cc96e5b28ef9d60a5b17fd2e8b008c39c0Hall Liu downloadResultIntent.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_REQUEST, request1); 383c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu downloadResultIntent.putExtra(VendorUtils.EXTRA_FINAL_URI, 384eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu tempFile.getFilePathUri()); 385d625298cd6d828d59ea41df2b6be24d0c44150b9Hall Liu downloadResultIntent.putExtra(MbmsDownloadSession.EXTRA_MBMS_FILE_INFO, fileToDownload); 386c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu downloadResultIntent.putExtra(VendorUtils.EXTRA_TEMP_FILE_ROOT, 387eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu mAppTempFileRoots.get(appKey)); 388264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu ArrayList<Uri> tempFileList = new ArrayList<>(1); 389eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu tempFileList.add(tempFile.getFilePathUri()); 390264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu downloadResultIntent.getExtras().putParcelableArrayList( 391c6b89ec244886b4d5223c8698d173f7dc5164bddHall Liu VendorUtils.EXTRA_TEMP_LIST, tempFileList); 392d625298cd6d828d59ea41df2b6be24d0c44150b9Hall Liu downloadResultIntent.putExtra(MbmsDownloadSession.EXTRA_MBMS_DOWNLOAD_RESULT, result); 393eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu downloadResultIntent.setComponent(mAppReceivers.get(appKey)); 394264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu 395264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu sendOrderedBroadcast(downloadResultIntent, 396264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu null, // receiverPermission 397264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu new BroadcastReceiver() { 398264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu @Override 399264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu public void onReceive(Context context, Intent intent) { 400264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu int resultCode = getResultCode(); 401264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu Log.i(LOG_TAG, "Download result ack: " + resultCode); 402264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu } 403264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu }, 404264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu null, // scheduler 405264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu Activity.RESULT_OK, 406264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu null, // initialData 407264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu null /* initialExtras */); 408264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu } 409eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu 410eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu private void checkInitialized(FrontendAppIdentifier appKey) { 411eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu if (!mAppCallbacks.containsKey(appKey)) { 412eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu throw new IllegalStateException("Not yet initialized"); 413eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu } 414eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu } 415eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu 416eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu private int getNumFdsNeededForRequest(DownloadRequest request) { 417d2860c33f4b1854fcfb13f2247c0e004463d034fHall Liu return FileServiceRepository.getInstance(this) 418d2860c33f4b1854fcfb13f2247c0e004463d034fHall Liu .getFileServiceInfoForId(request.getFileServiceId()).getFiles().size(); 419eab21d93e8bd66da35a770f7e61ae3f9483babdaHall Liu } 420434fb4c1f2796b91b79c5a6646518305487802abHall Liu 421434fb4c1f2796b91b79c5a6646518305487802abHall Liu private void addTempFileInUse(FrontendAppIdentifier appKey, String serviceId, Uri tempFileUri) { 422434fb4c1f2796b91b79c5a6646518305487802abHall Liu Map<String, Set<Uri>> tempFileByService = mTempFilesInUse.get(appKey); 423434fb4c1f2796b91b79c5a6646518305487802abHall Liu if (tempFileByService == null) { 424434fb4c1f2796b91b79c5a6646518305487802abHall Liu tempFileByService = new ConcurrentHashMap<>(); 425434fb4c1f2796b91b79c5a6646518305487802abHall Liu mTempFilesInUse.put(appKey, tempFileByService); 426434fb4c1f2796b91b79c5a6646518305487802abHall Liu } 427434fb4c1f2796b91b79c5a6646518305487802abHall Liu Set<Uri> tempFilesInUse = tempFileByService.get(serviceId); 428434fb4c1f2796b91b79c5a6646518305487802abHall Liu if (tempFilesInUse == null) { 429434fb4c1f2796b91b79c5a6646518305487802abHall Liu tempFilesInUse = ConcurrentHashMap.newKeySet(); 430434fb4c1f2796b91b79c5a6646518305487802abHall Liu tempFileByService.put(serviceId, tempFilesInUse); 431434fb4c1f2796b91b79c5a6646518305487802abHall Liu } 432434fb4c1f2796b91b79c5a6646518305487802abHall Liu tempFilesInUse.add(tempFileUri); 433434fb4c1f2796b91b79c5a6646518305487802abHall Liu } 434434fb4c1f2796b91b79c5a6646518305487802abHall Liu 435434fb4c1f2796b91b79c5a6646518305487802abHall Liu private void removeTempFileInUse(FrontendAppIdentifier appKey, String serviceId, 436434fb4c1f2796b91b79c5a6646518305487802abHall Liu Uri tempFileUri) { 437434fb4c1f2796b91b79c5a6646518305487802abHall Liu Set<Uri> tempFilesInUse = mTempFilesInUse.getOrDefault(appKey, Collections.emptyMap()) 438434fb4c1f2796b91b79c5a6646518305487802abHall Liu .getOrDefault(serviceId, Collections.emptySet()); 439434fb4c1f2796b91b79c5a6646518305487802abHall Liu if (tempFilesInUse.contains(tempFileUri)) { 440434fb4c1f2796b91b79c5a6646518305487802abHall Liu tempFilesInUse.remove(tempFileUri); 441434fb4c1f2796b91b79c5a6646518305487802abHall Liu } else { 442434fb4c1f2796b91b79c5a6646518305487802abHall Liu Log.w(LOG_TAG, "Trying to remove unknown temp file in use " + tempFileUri + " for app" + 443434fb4c1f2796b91b79c5a6646518305487802abHall Liu appKey + " and service id " + serviceId); 444434fb4c1f2796b91b79c5a6646518305487802abHall Liu } 445434fb4c1f2796b91b79c5a6646518305487802abHall Liu } 446264773f4a5c58f8d71e13e44ca74327621dc6365Hall Liu} 447