blob: 1335b52673d24965026fcc7c66b267d484da556d [file] [log] [blame]
/*
* Copyright (C) 2018 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.mbms.vendor;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.telephony.mbms.GroupCallCallback;
import android.telephony.mbms.IGroupCallCallback;
import android.telephony.mbms.IMbmsGroupCallSessionCallback;
import android.telephony.mbms.MbmsErrors;
import android.telephony.mbms.MbmsGroupCallSessionCallback;
import android.telephony.mbms.vendor.IMbmsGroupCallService.Stub;
import java.util.List;
/**
* Base class for MBMS group-call services. The middleware should override this class to implement
* its {@link Service} for group calls
* Subclasses should call this class's {@link #onBind} method to obtain an {@link IBinder} if they
* override {@link #onBind}.
* @hide
*/
@SystemApi
@TestApi
public class MbmsGroupCallServiceBase extends Service {
private final IBinder mInterface = new Stub() {
@Override
public int initialize(final IMbmsGroupCallSessionCallback callback,
final int subscriptionId) throws RemoteException {
if (callback == null) {
throw new NullPointerException("Callback must not be null");
}
final int uid = Binder.getCallingUid();
int result = MbmsGroupCallServiceBase.this.initialize(
new MbmsGroupCallSessionCallback() {
@Override
public void onError(final int errorCode, final String message) {
try {
if (errorCode == MbmsErrors.UNKNOWN) {
throw new IllegalArgumentException(
"Middleware cannot send an unknown error.");
}
callback.onError(errorCode, message);
} catch (RemoteException e) {
onAppCallbackDied(uid, subscriptionId);
}
}
@Override
public void onAvailableSaisUpdated(final List currentSais,
final List availableSais) {
try {
callback.onAvailableSaisUpdated(currentSais, availableSais);
} catch (RemoteException e) {
onAppCallbackDied(uid, subscriptionId);
}
}
@Override
public void onServiceInterfaceAvailable(final String interfaceName,
final int index) {
try {
callback.onServiceInterfaceAvailable(interfaceName, index);
} catch (RemoteException e) {
onAppCallbackDied(uid, subscriptionId);
}
}
@Override
public void onMiddlewareReady() {
try {
callback.onMiddlewareReady();
} catch (RemoteException e) {
onAppCallbackDied(uid, subscriptionId);
}
}
}, subscriptionId);
if (result == MbmsErrors.SUCCESS) {
callback.asBinder().linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
onAppCallbackDied(uid, subscriptionId);
}
}, 0);
}
return result;
}
@Override
public void stopGroupCall(int subId, long tmgi) {
MbmsGroupCallServiceBase.this.stopGroupCall(subId, tmgi);
}
@Override
public void updateGroupCall(int subscriptionId, long tmgi, List saiList,
List frequencyList) {
MbmsGroupCallServiceBase.this.updateGroupCall(
subscriptionId, tmgi, saiList, frequencyList);
}
@Override
public int startGroupCall(final int subscriptionId, final long tmgi,
final List saiList,
final List frequencyList, final IGroupCallCallback callback)
throws RemoteException {
if (callback == null) {
throw new NullPointerException("Callback must not be null");
}
final int uid = Binder.getCallingUid();
int result = MbmsGroupCallServiceBase.this.startGroupCall(
subscriptionId, tmgi, saiList, frequencyList, new GroupCallCallback() {
@Override
public void onError(final int errorCode, final String message) {
try {
if (errorCode == MbmsErrors.UNKNOWN) {
throw new IllegalArgumentException(
"Middleware cannot send an unknown error.");
}
callback.onError(errorCode, message);
} catch (RemoteException e) {
onAppCallbackDied(uid, subscriptionId);
}
}
public void onGroupCallStateChanged(int state, int reason) {
try {
callback.onGroupCallStateChanged(state, reason);
} catch (RemoteException e) {
onAppCallbackDied(uid, subscriptionId);
}
}
public void onBroadcastSignalStrengthUpdated(int signalStrength) {
try {
callback.onBroadcastSignalStrengthUpdated(signalStrength);
} catch (RemoteException e) {
onAppCallbackDied(uid, subscriptionId);
}
}
});
if (result == MbmsErrors.SUCCESS) {
callback.asBinder().linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
onAppCallbackDied(uid, subscriptionId);
}
}, 0);
}
return result;
}
@Override
public void dispose(int subId) throws RemoteException {
MbmsGroupCallServiceBase.this.dispose(subId);
}
};
/**
* Initialize the group call service for this app and subscription ID, registering the callback.
*
* May throw an {@link IllegalArgumentException} or a {@link SecurityException}, which
* will be intercepted and passed to the app as
* {@link MbmsErrors.InitializationErrtrors#ERROR_UNABLE_TO_INITIALIZE}
*
* May return any value from {@link MbmsErrors.InitializationErrors}
* or {@link MbmsErrors#SUCCESS}. Non-successful error codes will be passed to the app via
* {@link IMbmsGroupCallSessionCallback#onError(int, String)}.
*
* @param callback The callback to use to communicate with the app.
* @param subscriptionId The subscription ID to use.
*/
public int initialize(@NonNull MbmsGroupCallSessionCallback callback, int subscriptionId)
throws RemoteException {
throw new UnsupportedOperationException("Not implemented");
}
/**
* Starts a particular group call. This method may perform asynchronous work. When
* the call is ready for consumption, the middleware should inform the app via
* {@link IGroupCallCallback#onGroupCallStateChanged(int, int)}.
*
* May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
*
* @param subscriptionId The subscription id to use.
* @param tmgi The TMGI, an identifier for the group call.
* @param saiList A list of SAIs for the group call.
* @param frequencyList A list of frequencies for the group call.
* @param callback The callback object on which the app wishes to receive updates.
* @return Any error in {@link MbmsErrors.GeneralErrors}
*/
public int startGroupCall(int subscriptionId, long tmgi, @NonNull List<Integer> saiList,
@NonNull List<Integer> frequencyList, @NonNull GroupCallCallback callback) {
throw new UnsupportedOperationException("Not implemented");
}
/**
* Stop the group call identified by {@code tmgi}.
*
* The callback provided via {@link #startGroupCall} should no longer be
* used after this method has called by the app.
*
* May throw an {@link IllegalStateException}
*
* @param subscriptionId The subscription id to use.
* @param tmgi The TMGI for the call to stop.
*/
public void stopGroupCall(int subscriptionId, long tmgi) {
throw new UnsupportedOperationException("Not implemented");
}
/**
* Called when the app receives new SAI and frequency information for the group call identified
* by {@code tmgi}.
* @param saiList New list of SAIs that the call is available on.
* @param frequencyList New list of frequencies that the call is available on.
*/
public void updateGroupCall(int subscriptionId, long tmgi, @NonNull List<Integer> saiList,
@NonNull List<Integer> frequencyList) {
throw new UnsupportedOperationException("Not implemented");
}
/**
* Signals that the app wishes to dispose of the session identified by the
* {@code subscriptionId} argument and the caller's uid. No notification back to the
* app is required for this operation, and the corresponding callback provided via
* {@link #initialize} should no longer be used
* after this method has been called by the app.
*
* May throw an {@link IllegalStateException}
*
* @param subscriptionId The subscription id to use.
*/
public void dispose(int subscriptionId) throws RemoteException {
throw new UnsupportedOperationException("Not implemented");
}
/**
* Indicates that the app identified by the given UID and subscription ID has died.
* @param uid the UID of the app, as returned by {@link Binder#getCallingUid()}.
* @param subscriptionId The subscription ID the app is using.
*/
public void onAppCallbackDied(int uid, int subscriptionId) {
}
@Override
public IBinder onBind(Intent intent) {
return mInterface;
}
}