blob: 500da02ce8685edb92f78ccb1a8eac127545d121 [file] [log] [blame]
/*
* 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 android.telephony.cts.embmstestapp;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.RemoteException;
import android.telephony.mbms.DownloadRequest;
import android.telephony.mbms.DownloadStateCallback;
import android.telephony.mbms.FileServiceInfo;
import android.telephony.mbms.MbmsDownloadSessionCallback;
import android.telephony.mbms.MbmsErrors;
import android.telephony.mbms.vendor.MbmsDownloadServiceBase;
import android.util.Log;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
public class CtsDownloadService extends Service {
private static final Set<String> ALLOWED_PACKAGES = new HashSet<String>() {{
add("android.telephony.cts");
}};
private static final String TAG = "EmbmsTestDownload";
public static final String METHOD_NAME = "method_name";
public static final String METHOD_INITIALIZE = "initialize";
public static final String METHOD_REQUEST_UPDATE_FILE_SERVICES =
"requestUpdateFileServices";
public static final String METHOD_SET_TEMP_FILE_ROOT = "setTempFileRootDirectory";
public static final String METHOD_CLOSE = "close";
public static final String ARGUMENT_SUBSCRIPTION_ID = "subscriptionId";
public static final String ARGUMENT_SERVICE_CLASSES = "serviceClasses";
public static final String ARGUMENT_ROOT_DIRECTORY_PATH = "rootDirectoryPath";
public static final String CONTROL_INTERFACE_ACTION =
"android.telephony.cts.embmstestapp.ACTION_CONTROL_MIDDLEWARE";
public static final ComponentName CONTROL_INTERFACE_COMPONENT =
ComponentName.unflattenFromString(
"android.telephony.cts.embmstestapp/.CtsDownloadService");
public static final FileServiceInfo FILE_SERVICE_INFO;
static {
String id = "FileServiceId";
Map<Locale, String> localeDict = new HashMap<Locale, String>() {{
put(Locale.US, "Entertainment Source 1");
put(Locale.CANADA, "Entertainment Source 1, eh?");
}};
List<Locale> locales = new ArrayList<Locale>() {{
add(Locale.CANADA);
add(Locale.US);
}};
FILE_SERVICE_INFO = new FileServiceInfo(localeDict, "class1", locales,
id, new Date(2017, 8, 21, 18, 20, 29),
new Date(2017, 8, 21, 18, 23, 9), Collections.emptyList());
}
private MbmsDownloadSessionCallback mAppCallback;
private HandlerThread mHandlerThread;
private Handler mHandler;
private List<Bundle> mReceivedCalls = new LinkedList<>();
private int mErrorCodeOverride = MbmsErrors.SUCCESS;
private final MbmsDownloadServiceBase mDownloadServiceImpl = new MbmsDownloadServiceBase() {
@Override
public int initialize(int subscriptionId, MbmsDownloadSessionCallback callback) {
Bundle b = new Bundle();
b.putString(METHOD_NAME, METHOD_INITIALIZE);
b.putInt(ARGUMENT_SUBSCRIPTION_ID, subscriptionId);
mReceivedCalls.add(b);
if (mErrorCodeOverride != MbmsErrors.SUCCESS) {
return mErrorCodeOverride;
}
int packageUid = Binder.getCallingUid();
String[] packageNames = getPackageManager().getPackagesForUid(packageUid);
if (packageNames == null) {
return MbmsErrors.InitializationErrors.ERROR_APP_PERMISSIONS_NOT_GRANTED;
}
boolean isUidAllowed = Arrays.stream(packageNames).anyMatch(ALLOWED_PACKAGES::contains);
if (!isUidAllowed) {
return MbmsErrors.InitializationErrors.ERROR_APP_PERMISSIONS_NOT_GRANTED;
}
mHandler.post(() -> {
if (mAppCallback == null) {
mAppCallback = callback;
} else {
callback.onError(
MbmsErrors.InitializationErrors.ERROR_DUPLICATE_INITIALIZE, "");
return;
}
callback.onMiddlewareReady();
});
return MbmsErrors.SUCCESS;
}
@Override
public int requestUpdateFileServices(int subscriptionId, List<String> serviceClasses) {
Bundle b = new Bundle();
b.putString(METHOD_NAME, METHOD_REQUEST_UPDATE_FILE_SERVICES);
b.putInt(ARGUMENT_SUBSCRIPTION_ID, subscriptionId);
b.putStringArrayList(ARGUMENT_SERVICE_CLASSES, new ArrayList<>(serviceClasses));
mReceivedCalls.add(b);
if (mErrorCodeOverride != MbmsErrors.SUCCESS) {
return mErrorCodeOverride;
}
List<FileServiceInfo> serviceInfos = Collections.singletonList(FILE_SERVICE_INFO);
mHandler.post(() -> {
if (mAppCallback!= null) {
mAppCallback.onFileServicesUpdated(serviceInfos);
}
});
return MbmsErrors.SUCCESS;
}
@Override
public int setTempFileRootDirectory(int subscriptionId, String rootDirectoryPath) {
Bundle b = new Bundle();
b.putString(METHOD_NAME, METHOD_SET_TEMP_FILE_ROOT);
b.putInt(ARGUMENT_SUBSCRIPTION_ID, subscriptionId);
b.putString(ARGUMENT_ROOT_DIRECTORY_PATH, rootDirectoryPath);
mReceivedCalls.add(b);
return 0;
}
@Override
public int registerStateCallback(DownloadRequest downloadRequest,
DownloadStateCallback listener) throws RemoteException {
// TODO
return MbmsErrors.SUCCESS;
}
@Override
public void dispose(int subscriptionId) {
Bundle b = new Bundle();
b.putString(METHOD_NAME, METHOD_CLOSE);
b.putInt(ARGUMENT_SUBSCRIPTION_ID, subscriptionId);
mReceivedCalls.add(b);
// TODO
}
@Override
public void onAppCallbackDied(int uid, int subscriptionId) {
mAppCallback = null;
}
};
private final IBinder mControlInterface = new ICtsDownloadMiddlewareControl.Stub() {
@Override
public void reset() {
mReceivedCalls.clear();
mHandler.removeCallbacksAndMessages(null);
mAppCallback = null;
mErrorCodeOverride = MbmsErrors.SUCCESS;
}
@Override
public List<Bundle> getDownloadSessionCalls() {
return mReceivedCalls;
}
@Override
public void forceErrorCode(int error) {
mErrorCodeOverride = error;
}
@Override
public void fireErrorOnSession(int errorCode, String message) {
mHandler.post(() -> mAppCallback.onError(errorCode, message));
}
};
@Override
public void onDestroy() {
super.onCreate();
mHandlerThread.quitSafely();
logd("CtsDownloadService onDestroy");
}
@Override
public IBinder onBind(Intent intent) {
if (CONTROL_INTERFACE_ACTION.equals(intent.getAction())) {
logd("CtsDownloadService control interface bind");
return mControlInterface;
}
logd("CtsDownloadService onBind");
if (mHandlerThread != null && mHandlerThread.isAlive()) {
return mDownloadServiceImpl;
}
mHandlerThread = new HandlerThread("CtsDownloadServiceWorker");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
return mDownloadServiceImpl;
}
private static void logd(String s) {
Log.d(TAG, s);
}
private void checkInitialized() {
if (mAppCallback == null) {
throw new IllegalStateException("Not yet initialized");
}
}
}