Embms download part 2
Add support for multi-part file downloads.
Improves destination directory handling in the download process.
Change-Id: I7df0f4a90ea09a88bc9eb487597240cd51b912b6
diff --git a/testapps/EmbmsServiceTestApp/Android.mk b/testapps/EmbmsServiceTestApp/Android.mk
index 874fad2..d8c4493 100644
--- a/testapps/EmbmsServiceTestApp/Android.mk
+++ b/testapps/EmbmsServiceTestApp/Android.mk
@@ -13,8 +13,7 @@
LOCAL_CERTIFICATE := platform
LOCAL_PRIVILEGED_MODULE := true
-# Change the following to "debug" to build the EmbmsTestService into the userdebug build.
-LOCAL_MODULE_TAGS := optional
-#LOCAL_MODULE_TAGS := debug
+# Uncomment the following line to build the EmbmsTestService into the userdebug build.
+# LOCAL_MODULE_TAGS := debug
include $(BUILD_PACKAGE)
diff --git a/testapps/EmbmsServiceTestApp/res/raw/sheep.png b/testapps/EmbmsServiceTestApp/res/raw/sheep.png
new file mode 100644
index 0000000..650966c
--- /dev/null
+++ b/testapps/EmbmsServiceTestApp/res/raw/sheep.png
Binary files differ
diff --git a/testapps/EmbmsServiceTestApp/res/raw/snake.png b/testapps/EmbmsServiceTestApp/res/raw/snake.png
new file mode 100644
index 0000000..6fa6c8b
--- /dev/null
+++ b/testapps/EmbmsServiceTestApp/res/raw/snake.png
Binary files differ
diff --git a/testapps/EmbmsServiceTestApp/res/raw/s1.png b/testapps/EmbmsServiceTestApp/res/raw/suntree.png
similarity index 100%
rename from testapps/EmbmsServiceTestApp/res/raw/s1.png
rename to testapps/EmbmsServiceTestApp/res/raw/suntree.png
Binary files differ
diff --git a/testapps/EmbmsServiceTestApp/res/raw/unicorn.png b/testapps/EmbmsServiceTestApp/res/raw/unicorn.png
new file mode 100644
index 0000000..3146344
--- /dev/null
+++ b/testapps/EmbmsServiceTestApp/res/raw/unicorn.png
Binary files differ
diff --git a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/AppActiveStreams.java b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/AppActiveStreams.java
index 6a0f61e..9b3cc6b 100644
--- a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/AppActiveStreams.java
+++ b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/AppActiveStreams.java
@@ -67,10 +67,10 @@
// Stores the state and callback per service ID.
private final Map<String, StreamCallbackWithState> mStreamStates = new HashMap<>();
- private final StreamingAppIdentifier mAppIdentifier;
+ private final FrontendAppIdentifier mAppIdentifier;
private final Random mRand = new Random();
- public AppActiveStreams(StreamingAppIdentifier appIdentifier) {
+ public AppActiveStreams(FrontendAppIdentifier appIdentifier) {
mAppIdentifier = appIdentifier;
}
diff --git a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java
index 360dd15..490f3fa 100644
--- a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java
+++ b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsSampleDownloadService.java
@@ -29,10 +29,13 @@
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
import android.telephony.MbmsDownloadManager;
import android.telephony.mbms.DownloadRequest;
+import android.telephony.mbms.FileInfo;
+import android.telephony.mbms.FileServiceInfo;
import android.telephony.mbms.IDownloadCallback;
-import android.telephony.mbms.MbmsDownloadReceiver;
+import android.telephony.mbms.IMbmsDownloadManagerCallback;
import android.telephony.mbms.MbmsException;
import android.telephony.mbms.UriPathPair;
import android.telephony.mbms.vendor.IMbmsDownloadService;
@@ -44,33 +47,111 @@
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
public class EmbmsSampleDownloadService extends Service {
+ private static final Set<String> ALLOWED_PACKAGES = new HashSet<String>() {{
+ add("com.android.phone.testapps.embmsdownload");
+ }};
+
private static final String LOG_TAG = "EmbmsSampleDownload";
+ private static final long SEND_FILE_SERVICE_INFO_DELAY = 500;
private static final long DOWNLOAD_DELAY_MS = 1000;
+ private static final long FILE_SEPARATION_DELAY = 500;
private final IMbmsDownloadService mBinder = new MbmsDownloadServiceBase() {
@Override
- public int download(DownloadRequest downloadRequest, IDownloadCallback listener) {
- // TODO: move this package name finding logic to initialize()
+ public void initialize(String appName, int subId, IMbmsDownloadManagerCallback listener) {
String[] packageNames = getPackageManager().getPackagesForUid(Binder.getCallingUid());
if (packageNames == null) {
throw new SecurityException("No matching packages found for your UID");
}
-
- if (packageNames.length != 1) {
- throw new IllegalStateException("More than one package found for your UID");
+ boolean isUidAllowed = Arrays.stream(packageNames).anyMatch(ALLOWED_PACKAGES::contains);
+ if (!isUidAllowed) {
+ throw new SecurityException("No packages for your UID are allowed to use this " +
+ "service");
}
- String packageName = packageNames[0];
+ FrontendAppIdentifier appKey =
+ new FrontendAppIdentifier(Binder.getCallingUid(), appName, subId);
+ if (!mAppCallbacks.containsKey(appKey)) {
+ mAppCallbacks.put(appKey, listener);
+ ComponentName appReceiver = MbmsDownloadManager.getAppReceiverFromUid(
+ EmbmsSampleDownloadService.this, Binder.getCallingUid());
+ mAppReceivers.put(appKey, appReceiver);
+ } else {
+ // Stick the error callback on a different thread so that we're not calling back
+ // to the app on the same thread.
+ mHandler.post(() -> {
+ try {
+ listener.error(MbmsException.ERROR_ALREADY_INITIALIZED, "");
+ } catch (RemoteException e) {
+ // ignore, it was an error anyway
+ }
+ });
+ }
+ }
- mHandler.post(() -> sendFdRequest(downloadRequest, packageName, 1));
+ @Override
+ public int getFileServices(String appName, int subscriptionId,
+ List<String> serviceClasses) throws RemoteException {
+ FrontendAppIdentifier appKey =
+ new FrontendAppIdentifier(Binder.getCallingUid(), appName, subscriptionId);
+ checkInitialized(appKey);
+
+ List<FileServiceInfo> serviceInfos =
+ FileServiceRepository.getInstance(EmbmsSampleDownloadService.this)
+ .getFileServicesForClasses(serviceClasses);
+
+ mHandler.postDelayed(() -> {
+ try {
+ IMbmsDownloadManagerCallback appCallback = mAppCallbacks.get(appKey);
+ appCallback.fileServicesUpdated(serviceInfos);
+ } catch (RemoteException e) {
+ // TODO: call dispose
+ }
+ }, SEND_FILE_SERVICE_INFO_DELAY);
+ return MbmsException.SUCCESS;
+ }
+
+ @Override
+ public int setTempFileRootDirectory(String appName, int subscriptionId,
+ String rootDirectoryPath) throws RemoteException {
+ FrontendAppIdentifier appKey =
+ new FrontendAppIdentifier(Binder.getCallingUid(), appName, subscriptionId);
+ checkInitialized(appKey);
+
+ if (mDoesAppHaveActiveDownload.getOrDefault(appKey, false)) {
+ return MbmsException.ERROR_CANNOT_CHANGE_TEMP_FILE_ROOT;
+ }
+ mAppTempFileRoots.put(appKey, rootDirectoryPath);
+ return MbmsException.SUCCESS;
+ }
+
+ @Override
+ public int download(DownloadRequest downloadRequest, IDownloadCallback listener) {
+ FrontendAppIdentifier appKey = new FrontendAppIdentifier(
+ Binder.getCallingUid(), downloadRequest.getAppName(),
+ downloadRequest.getSubscriptionId());
+ checkInitialized(appKey);
+
+ mHandler.post(() -> sendFdRequest(downloadRequest, appKey));
return MbmsException.SUCCESS;
}
};
+ private final Map<FrontendAppIdentifier, IMbmsDownloadManagerCallback> mAppCallbacks =
+ new HashMap<>();
+ private final Map<FrontendAppIdentifier, ComponentName> mAppReceivers = new HashMap<>();
+ private final Map<FrontendAppIdentifier, String> mAppTempFileRoots = new HashMap<>();
+ private final Map<FrontendAppIdentifier, Boolean> mDoesAppHaveActiveDownload =
+ new ConcurrentHashMap<>();
+
private HandlerThread mHandlerThread;
private Handler mHandler;
@@ -82,14 +163,15 @@
return mBinder.asBinder();
}
- private void sendFdRequest(DownloadRequest request, String packageName, int numFds) {
+ private void sendFdRequest(DownloadRequest request, FrontendAppIdentifier appKey) {
+ int numFds = getNumFdsNeededForRequest(request);
// Compose the FILE_DESCRIPTOR_REQUEST_INTENT
Intent requestIntent = new Intent(MbmsDownloadManager.ACTION_FILE_DESCRIPTOR_REQUEST);
requestIntent.putExtra(MbmsDownloadManager.EXTRA_REQUEST, request);
requestIntent.putExtra(MbmsDownloadManager.EXTRA_FD_COUNT, numFds);
- ComponentName mbmsReceiverComponent = new ComponentName(packageName,
- MbmsDownloadReceiver.class.getCanonicalName());
- requestIntent.setComponent(mbmsReceiverComponent);
+ requestIntent.putExtra(MbmsDownloadManager.EXTRA_TEMP_FILE_ROOT,
+ mAppTempFileRoots.get(appKey));
+ requestIntent.setComponent(mAppReceivers.get(appKey));
// Send as an ordered broadcast, using a BroadcastReceiver to capture the result
// containing UriPathPairs.
@@ -102,7 +184,7 @@
// This delay is to emulate the time it'd usually take to fetch the file
// off the network.
mHandler.postDelayed(
- () -> performDownload(request, packageName, resultExtras),
+ () -> performDownload(request, appKey, resultExtras),
DOWNLOAD_DELAY_MS);
}
},
@@ -112,25 +194,52 @@
null /* initialExtras */);
}
- private void performDownload(DownloadRequest request, String packageName, Bundle extras) {
- int result = MbmsDownloadManager.RESULT_SUCCESSFUL;
+ private void performDownload(DownloadRequest request, FrontendAppIdentifier appKey,
+ Bundle extras) {
List<UriPathPair> tempFiles = extras.getParcelableArrayList(
MbmsDownloadManager.EXTRA_FREE_URI_LIST);
- Uri tempFilePathUri = tempFiles.get(0).getFilePathUri();
- Uri freeTempFileUri = tempFiles.get(0).getContentUri();
+ List<FileInfo> filesToDownload = request.getFileServiceInfo().getFiles();
+ if (tempFiles.size() != filesToDownload.size()) {
+ Log.w(LOG_TAG, "Different numbers of temp files and files to download...");
+ }
+
+ // Go through the files one-by-one and send them to the frontend app with a delay between
+ // each one.
+ mDoesAppHaveActiveDownload.put(appKey, true);
+ for (int i = 0; i < tempFiles.size(); i++) {
+ if (i >= filesToDownload.size()) {
+ break;
+ }
+ UriPathPair tempFile = tempFiles.get(i);
+ FileInfo fileToDownload = filesToDownload.get(i);
+ final boolean isLastFile = i == tempFiles.size() - 1;
+ mHandler.postDelayed(() -> {
+ downloadSingleFile(appKey, request, tempFile, fileToDownload);
+ if (isLastFile) {
+ mDoesAppHaveActiveDownload.put(appKey, false);
+ }
+ }, FILE_SEPARATION_DELAY * i);
+ }
+ }
+
+ private void downloadSingleFile(FrontendAppIdentifier appKey, DownloadRequest request,
+ UriPathPair tempFile, FileInfo fileToDownload) {
+ int result = MbmsDownloadManager.RESULT_SUCCESSFUL;
try {
// Get the ParcelFileDescriptor for the single temp file we requested
- ParcelFileDescriptor tempFile = getContentResolver().openFileDescriptor(
- freeTempFileUri, "rw");
+ ParcelFileDescriptor tempFileFd = getContentResolver().openFileDescriptor(
+ tempFile.getContentUri(), "rw");
OutputStream destinationStream =
- new ParcelFileDescriptor.AutoCloseOutputStream(tempFile);
+ new ParcelFileDescriptor.AutoCloseOutputStream(tempFileFd);
// This is how you get the native fd
- Log.i(LOG_TAG, "Native fd: " + tempFile.getFd());
+ Log.i(LOG_TAG, "Native fd: " + tempFileFd.getFd());
+ int resourceId = FileServiceRepository.getInstance(this)
+ .getResourceForFileUri(fileToDownload.getUri());
// Open the picture we have in our res/raw directory
- InputStream image = getResources().openRawResource(R.raw.s1);
+ InputStream image = getResources().openRawResource(resourceId);
// Copy it into the temp file in the app's file space (crudely)
byte[] imageBuffer = new byte[image.available()];
@@ -144,16 +253,17 @@
Intent downloadResultIntent =
new Intent(MbmsDownloadManager.ACTION_DOWNLOAD_RESULT_INTERNAL);
downloadResultIntent.putExtra(MbmsDownloadManager.EXTRA_REQUEST, request);
- downloadResultIntent.putExtra(MbmsDownloadManager.EXTRA_FINAL_URI, tempFilePathUri);
+ downloadResultIntent.putExtra(MbmsDownloadManager.EXTRA_FINAL_URI,
+ tempFile.getFilePathUri());
+ downloadResultIntent.putExtra(MbmsDownloadManager.EXTRA_FILE_INFO, fileToDownload);
+ downloadResultIntent.putExtra(MbmsDownloadManager.EXTRA_TEMP_FILE_ROOT,
+ mAppTempFileRoots.get(appKey));
ArrayList<Uri> tempFileList = new ArrayList<>(1);
- tempFileList.add(tempFilePathUri);
+ tempFileList.add(tempFile.getFilePathUri());
downloadResultIntent.getExtras().putParcelableArrayList(
MbmsDownloadManager.EXTRA_TEMP_LIST, tempFileList);
downloadResultIntent.putExtra(MbmsDownloadManager.EXTRA_RESULT, result);
-
- ComponentName mbmsReceiverComponent = new ComponentName(packageName,
- MbmsDownloadReceiver.class.getCanonicalName());
- downloadResultIntent.setComponent(mbmsReceiverComponent);
+ downloadResultIntent.setComponent(mAppReceivers.get(appKey));
sendOrderedBroadcast(downloadResultIntent,
null, // receiverPermission
@@ -169,4 +279,14 @@
null, // initialData
null /* initialExtras */);
}
+
+ private void checkInitialized(FrontendAppIdentifier appKey) {
+ if (!mAppCallbacks.containsKey(appKey)) {
+ throw new IllegalStateException("Not yet initialized");
+ }
+ }
+
+ private int getNumFdsNeededForRequest(DownloadRequest request) {
+ return request.getFileServiceInfo().getFiles().size();
+ }
}
diff --git a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsTestStreamingService.java b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsTestStreamingService.java
index 9758d49..11a9bde 100644
--- a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsTestStreamingService.java
+++ b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/EmbmsTestStreamingService.java
@@ -54,7 +54,7 @@
private static final int SEND_STREAMING_SERVICES_LIST = 1;
- private final Map<StreamingAppIdentifier, IMbmsStreamingManagerCallback> mAppCallbacks =
+ private final Map<FrontendAppIdentifier, IMbmsStreamingManagerCallback> mAppCallbacks =
new HashMap<>();
private HandlerThread mHandlerThread;
@@ -63,7 +63,7 @@
switch (msg.what) {
case SEND_STREAMING_SERVICES_LIST:
SomeArgs args = (SomeArgs) msg.obj;
- StreamingAppIdentifier appKey = (StreamingAppIdentifier) args.arg1;
+ FrontendAppIdentifier appKey = (FrontendAppIdentifier) args.arg1;
List<StreamingServiceInfo> services = (List) args.arg2;
IMbmsStreamingManagerCallback appCallback = mAppCallbacks.get(appKey);
if (appCallback != null) {
@@ -91,8 +91,8 @@
"service");
}
- StreamingAppIdentifier appKey =
- new StreamingAppIdentifier(Binder.getCallingUid(), appName, subId);
+ FrontendAppIdentifier appKey =
+ new FrontendAppIdentifier(Binder.getCallingUid(), appName, subId);
if (!mAppCallbacks.containsKey(appKey)) {
mAppCallbacks.put(appKey, listener);
} else {
@@ -104,8 +104,8 @@
@Override
public int getStreamingServices(String appName, int subscriptionId,
List<String> serviceClasses) {
- StreamingAppIdentifier appKey =
- new StreamingAppIdentifier(Binder.getCallingUid(), appName, subscriptionId);
+ FrontendAppIdentifier appKey =
+ new FrontendAppIdentifier(Binder.getCallingUid(), appName, subscriptionId);
checkInitialized(appKey);
List<StreamingServiceInfo> serviceInfos =
@@ -125,8 +125,8 @@
@Override
public int startStreaming(String appName, int subscriptionId, String serviceId,
IStreamingServiceCallback callback) {
- StreamingAppIdentifier appKey =
- new StreamingAppIdentifier(Binder.getCallingUid(), appName, subscriptionId);
+ FrontendAppIdentifier appKey =
+ new FrontendAppIdentifier(Binder.getCallingUid(), appName, subscriptionId);
checkInitialized(appKey);
checkServiceExists(serviceId);
@@ -143,8 +143,8 @@
@Override
public Uri getPlaybackUri(String appName, int subscriptionId, String serviceId) {
- StreamingAppIdentifier appKey =
- new StreamingAppIdentifier(Binder.getCallingUid(), appName, subscriptionId);
+ FrontendAppIdentifier appKey =
+ new FrontendAppIdentifier(Binder.getCallingUid(), appName, subscriptionId);
checkInitialized(appKey);
checkServiceExists(serviceId);
@@ -157,8 +157,8 @@
@Override
public void stopStreaming(String appName, int subscriptionId, String serviceId) {
- StreamingAppIdentifier appKey =
- new StreamingAppIdentifier(Binder.getCallingUid(), appName, subscriptionId);
+ FrontendAppIdentifier appKey =
+ new FrontendAppIdentifier(Binder.getCallingUid(), appName, subscriptionId);
checkInitialized(appKey);
checkServiceExists(serviceId);
@@ -167,8 +167,8 @@
@Override
public void disposeStream(String appName, int subscriptionId, String serviceId) {
- StreamingAppIdentifier appKey =
- new StreamingAppIdentifier(Binder.getCallingUid(), appName, subscriptionId);
+ FrontendAppIdentifier appKey =
+ new FrontendAppIdentifier(Binder.getCallingUid(), appName, subscriptionId);
checkInitialized(appKey);
checkServiceExists(serviceId);
@@ -178,8 +178,8 @@
@Override
public void dispose(String appName, int subscriptionId) {
- StreamingAppIdentifier appKey =
- new StreamingAppIdentifier(Binder.getCallingUid(), appName, subscriptionId);
+ FrontendAppIdentifier appKey =
+ new FrontendAppIdentifier(Binder.getCallingUid(), appName, subscriptionId);
checkInitialized(appKey);
Log.i(TAG, "Disposing app " + appName);
@@ -208,7 +208,7 @@
Log.d(TAG, s);
}
- private void checkInitialized(StreamingAppIdentifier appKey) {
+ private void checkInitialized(FrontendAppIdentifier appKey) {
if (!mAppCallbacks.containsKey(appKey)) {
throw new IllegalStateException("Not yet initialized");
}
diff --git a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/FileServiceRepository.java b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/FileServiceRepository.java
new file mode 100644
index 0000000..4d0b6c3
--- /dev/null
+++ b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/FileServiceRepository.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.phone.testapps.embmsmw;
+
+import android.content.Context;
+import android.net.Uri;
+import android.telephony.mbms.FileInfo;
+import android.telephony.mbms.FileServiceInfo;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class FileServiceRepository {
+ private int sServiceIdCounter = 0;
+ private final Map<String, FileServiceInfo> mIdToServiceInfo = new HashMap<>();
+ private final Map<Uri, Integer> mFileUriToResource = new HashMap<>();
+
+ private static final String FILE_DOWNLOAD_SCHEME = "filedownload";
+ private static final String FILE_AUTHORITY = "com.android.phone.testapps";
+
+ private static FileServiceRepository sInstance;
+ public static FileServiceRepository getInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = new FileServiceRepository(context);
+ }
+ return sInstance;
+ }
+
+ private final Context mContext;
+
+ private FileServiceRepository(Context context) {
+ mContext = context;
+ Uri sunAndTree = initFile("sunAndTree.png", R.raw.suntree);
+ Uri snake = initFile("animals/snake.png", R.raw.snake);
+ Uri unicorn = initFile("animals/unicorn.png", R.raw.unicorn);
+ Uri sheep = initFile("animals/sheep.png", R.raw.sheep);
+
+ createFileService("Class1", sunAndTree);
+ createFileService("Class1", snake, unicorn, sheep);
+ }
+
+ public List<FileServiceInfo> getFileServicesForClasses(
+ List<String> serviceClasses) {
+ return mIdToServiceInfo.values().stream()
+ .filter((info) -> serviceClasses.contains(info.getClassName()))
+ .collect(Collectors.toList());
+ }
+
+ public FileServiceInfo getFileServiceInfoForId(String serviceId) {
+ return mIdToServiceInfo.getOrDefault(serviceId, null);
+ }
+
+ public int getResourceForFileUri(Uri uri) {
+ return mFileUriToResource.getOrDefault(uri, 0);
+ }
+
+ private void createFileService(String className, Uri... filesIncluded) {
+ sServiceIdCounter++;
+ String id = "FileServiceId[" + sServiceIdCounter + "]";
+ List<Locale> locales = new ArrayList<Locale>(2) {{
+ add(Locale.US);
+ add(Locale.UK);
+ }};
+ Map<Locale, String> localeDict = new HashMap<Locale, String>() {{
+ put(Locale.US, "File Source " + sServiceIdCounter);
+ put(Locale.UK, "File Source with extra vowels " + sServiceIdCounter);
+ }};
+ List<FileInfo> fileInfos = Arrays.stream(filesIncluded)
+ .map(this::getFileInfoForUri)
+ .collect(Collectors.toList());
+ FileServiceInfo info = new FileServiceInfo(localeDict, className, locales,
+ id, new Date(System.currentTimeMillis() - 10000),
+ new Date(System.currentTimeMillis() + 10000),
+ fileInfos);
+ mIdToServiceInfo.put(id, info);
+ }
+
+ private Uri initFile(String relPath, int resource) {
+ Uri uri = new Uri.Builder()
+ .scheme(FILE_DOWNLOAD_SCHEME)
+ .authority(FILE_AUTHORITY)
+ .path(relPath)
+ .build();
+ mFileUriToResource.put(uri, resource);
+ return uri;
+ }
+
+ private FileInfo getFileInfoForUri(Uri uri) {
+ if (!mFileUriToResource.containsKey(uri)) {
+ return null;
+ }
+
+ InputStream fileIn = mContext.getResources().openRawResource(mFileUriToResource.get(uri));
+ int fileSize;
+ byte[] buffer;
+ byte[] md5Sum;
+ try {
+ fileSize = fileIn.available();
+ buffer = new byte[fileIn.available()];
+ fileIn.read(buffer);
+ } catch (IOException e) {
+ // ignore and just return null
+ return null;
+ }
+ try {
+ md5Sum = MessageDigest.getInstance("MD5").digest(buffer);
+ } catch (NoSuchAlgorithmException e) {
+ return null;
+ }
+ return new FileInfo(uri, "application/octet-stream", fileSize, md5Sum);
+ }
+}
diff --git a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/StreamingAppIdentifier.java b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/FrontendAppIdentifier.java
similarity index 90%
rename from testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/StreamingAppIdentifier.java
rename to testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/FrontendAppIdentifier.java
index 7cbb14a..4fb46aa 100644
--- a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/StreamingAppIdentifier.java
+++ b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/FrontendAppIdentifier.java
@@ -16,12 +16,12 @@
package com.android.phone.testapps.embmsmw;
-public class StreamingAppIdentifier {
+public class FrontendAppIdentifier {
private final int uid;
private final String appName;
private final int subscriptionId;
- public StreamingAppIdentifier(int uid, String appName, int subscriptionId) {
+ public FrontendAppIdentifier(int uid, String appName, int subscriptionId) {
this.uid = uid;
this.appName = appName;
this.subscriptionId = subscriptionId;
@@ -48,7 +48,7 @@
return false;
}
- StreamingAppIdentifier that = (StreamingAppIdentifier) o;
+ FrontendAppIdentifier that = (FrontendAppIdentifier) o;
if (uid != that.uid) {
return false;
diff --git a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/StreamStateTracker.java b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/StreamStateTracker.java
index e340b11..bb9494d 100644
--- a/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/StreamStateTracker.java
+++ b/testapps/EmbmsServiceTestApp/src/com/android/phone/testapps/embmsmw/StreamStateTracker.java
@@ -27,10 +27,10 @@
public class StreamStateTracker {
private static final String LOG_TAG = "MbmsStreamStateTracker";
- private static final Map<StreamingAppIdentifier, AppActiveStreams>
+ private static final Map<FrontendAppIdentifier, AppActiveStreams>
sPerAppStreamStates = new HashMap<>();
- public static int getStreamingState(StreamingAppIdentifier appIdentifier, String serviceId) {
+ public static int getStreamingState(FrontendAppIdentifier appIdentifier, String serviceId) {
AppActiveStreams appStreams = sPerAppStreamStates.get(appIdentifier);
if (appStreams == null) {
return StreamingService.STATE_STOPPED;
@@ -38,7 +38,7 @@
return appStreams.getStateForService(serviceId);
}
- public static void startStreaming(StreamingAppIdentifier appIdentifier, String serviceId,
+ public static void startStreaming(FrontendAppIdentifier appIdentifier, String serviceId,
IStreamingServiceCallback callback) {
AppActiveStreams appStreams = sPerAppStreamStates.get(appIdentifier);
if (appStreams == null) {
@@ -49,7 +49,7 @@
appStreams.startStreaming(serviceId, callback);
}
- public static void stopStreaming(StreamingAppIdentifier appIdentifier, String serviceId) {
+ public static void stopStreaming(FrontendAppIdentifier appIdentifier, String serviceId) {
Log.i(LOG_TAG, "Stopping stream " + serviceId);
AppActiveStreams appStreams = sPerAppStreamStates.get(appIdentifier);
if (appStreams == null) {
@@ -59,7 +59,7 @@
appStreams.stopStreaming(serviceId);
}
- public static void dispose(StreamingAppIdentifier appIdentifier, String serviceId) {
+ public static void dispose(FrontendAppIdentifier appIdentifier, String serviceId) {
AppActiveStreams appStreams = sPerAppStreamStates.get(appIdentifier);
if (appStreams == null) {
// We have no record of this app, so we can just move on.
@@ -68,7 +68,7 @@
appStreams.dispose(serviceId);
}
- public static void disposeAll(StreamingAppIdentifier appIdentifier) {
+ public static void disposeAll(FrontendAppIdentifier appIdentifier) {
sPerAppStreamStates.remove(appIdentifier);
}