Merge "Add the EMBMS group call API"
am: 52a8fdb7bd
Change-Id: Id9bf8b76532001c56e12633d882357e8757202d6
This commit is contained in:
@@ -506,11 +506,14 @@ java_defaults {
|
||||
"telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl",
|
||||
"telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl",
|
||||
"telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl",
|
||||
"telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl",
|
||||
"telephony/java/android/telephony/mbms/IDownloadStatusListener.aidl",
|
||||
"telephony/java/android/telephony/mbms/IDownloadProgressListener.aidl",
|
||||
"telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl",
|
||||
"telephony/java/android/telephony/mbms/IGroupCallCallback.aidl",
|
||||
"telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl",
|
||||
"telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl",
|
||||
"telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl",
|
||||
"telephony/java/android/telephony/INetworkService.aidl",
|
||||
"telephony/java/android/telephony/INetworkServiceCallback.aidl",
|
||||
"telephony/java/com/android/ims/internal/IImsCallSession.aidl",
|
||||
|
||||
@@ -42250,6 +42250,13 @@ package android.telephony {
|
||||
field public static final int STATUS_UNKNOWN = 0; // 0x0
|
||||
}
|
||||
|
||||
public class MbmsGroupCallSession implements java.lang.AutoCloseable {
|
||||
method public void close();
|
||||
method public static android.telephony.MbmsGroupCallSession create(android.content.Context, java.util.concurrent.Executor, int, android.telephony.mbms.MbmsGroupCallSessionCallback);
|
||||
method public static android.telephony.MbmsGroupCallSession create(android.content.Context, java.util.concurrent.Executor, android.telephony.mbms.MbmsGroupCallSessionCallback);
|
||||
method public android.telephony.mbms.GroupCall startGroupCall(java.util.concurrent.Executor, long, int[], int[], android.telephony.mbms.GroupCallCallback);
|
||||
}
|
||||
|
||||
public class MbmsStreamingSession implements java.lang.AutoCloseable {
|
||||
method public void close();
|
||||
method public static android.telephony.MbmsStreamingSession create(android.content.Context, java.util.concurrent.Executor, int, android.telephony.mbms.MbmsStreamingSessionCallback);
|
||||
@@ -43195,6 +43202,29 @@ package android.telephony.mbms {
|
||||
field public static final android.os.Parcelable.Creator<android.telephony.mbms.FileServiceInfo> CREATOR;
|
||||
}
|
||||
|
||||
public class GroupCall implements java.lang.AutoCloseable {
|
||||
method public void close();
|
||||
method public long getTmgi();
|
||||
method public void updateGroupCall(int[], int[]);
|
||||
field public static final int REASON_BY_USER_REQUEST = 1; // 0x1
|
||||
field public static final int REASON_FREQUENCY_CONFLICT = 3; // 0x3
|
||||
field public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 6; // 0x6
|
||||
field public static final int REASON_NONE = 0; // 0x0
|
||||
field public static final int REASON_NOT_CONNECTED_TO_HOMECARRIER_LTE = 5; // 0x5
|
||||
field public static final int REASON_OUT_OF_MEMORY = 4; // 0x4
|
||||
field public static final int STATE_STALLED = 3; // 0x3
|
||||
field public static final int STATE_STARTED = 2; // 0x2
|
||||
field public static final int STATE_STOPPED = 1; // 0x1
|
||||
}
|
||||
|
||||
public class GroupCallCallback {
|
||||
ctor public GroupCallCallback();
|
||||
method public void onBroadcastSignalStrengthUpdated(int);
|
||||
method public void onError(int, java.lang.String);
|
||||
method public void onGroupCallStateChanged(int, int);
|
||||
field public static final int SIGNAL_STRENGTH_UNAVAILABLE = -1; // 0xffffffff
|
||||
}
|
||||
|
||||
public class MbmsDownloadReceiver extends android.content.BroadcastReceiver {
|
||||
ctor public MbmsDownloadReceiver();
|
||||
method public void onReceive(android.content.Context, android.content.Intent);
|
||||
@@ -43243,6 +43273,14 @@ package android.telephony.mbms {
|
||||
field public static final int ERROR_UNABLE_TO_START_SERVICE = 302; // 0x12e
|
||||
}
|
||||
|
||||
public class MbmsGroupCallSessionCallback {
|
||||
ctor public MbmsGroupCallSessionCallback();
|
||||
method public void onAvailableSaisUpdated(java.util.List<java.lang.Integer>, java.util.List<java.util.List<java.lang.Integer>>);
|
||||
method public void onError(int, java.lang.String);
|
||||
method public void onMiddlewareReady();
|
||||
method public void onServiceInterfaceAvailable(java.lang.String, int);
|
||||
}
|
||||
|
||||
public class MbmsStreamingSessionCallback {
|
||||
ctor public MbmsStreamingSessionCallback();
|
||||
method public void onError(int, java.lang.String);
|
||||
|
||||
@@ -5075,6 +5075,10 @@ package android.telephony {
|
||||
field public static final java.lang.String MBMS_DOWNLOAD_SERVICE_ACTION = "android.telephony.action.EmbmsDownload";
|
||||
}
|
||||
|
||||
public class MbmsGroupCallSession implements java.lang.AutoCloseable {
|
||||
field public static final java.lang.String MBMS_GROUP_CALL_SERVICE_ACTION = "android.telephony.action.EmbmsGroupCall";
|
||||
}
|
||||
|
||||
public class MbmsStreamingSession implements java.lang.AutoCloseable {
|
||||
field public static final java.lang.String MBMS_STREAMING_SERVICE_ACTION = "android.telephony.action.EmbmsStreaming";
|
||||
}
|
||||
@@ -6375,6 +6379,17 @@ package android.telephony.mbms.vendor {
|
||||
method public int setTempFileRootDirectory(int, java.lang.String) throws android.os.RemoteException;
|
||||
}
|
||||
|
||||
public class MbmsGroupCallServiceBase extends android.app.Service {
|
||||
ctor public MbmsGroupCallServiceBase();
|
||||
method public void dispose(int) throws android.os.RemoteException;
|
||||
method public int initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int) throws android.os.RemoteException;
|
||||
method public void onAppCallbackDied(int, int);
|
||||
method public android.os.IBinder onBind(android.content.Intent);
|
||||
method public int startGroupCall(int, long, int[], int[], android.telephony.mbms.GroupCallCallback);
|
||||
method public void stopGroupCall(int, long);
|
||||
method public void updateGroupCall(int, long, int[], int[]);
|
||||
}
|
||||
|
||||
public class MbmsStreamingServiceBase extends android.os.Binder {
|
||||
ctor public MbmsStreamingServiceBase();
|
||||
method public void dispose(int) throws android.os.RemoteException;
|
||||
|
||||
@@ -966,6 +966,10 @@ package android.telephony {
|
||||
field public static final java.lang.String MBMS_DOWNLOAD_SERVICE_OVERRIDE_METADATA = "mbms-download-service-override";
|
||||
}
|
||||
|
||||
public class MbmsGroupCallSession implements java.lang.AutoCloseable {
|
||||
field public static final java.lang.String MBMS_GROUP_CALL_SERVICE_OVERRIDE_METADATA = "mbms-group-call-service-override";
|
||||
}
|
||||
|
||||
public class MbmsStreamingSession implements java.lang.AutoCloseable {
|
||||
field public static final java.lang.String MBMS_STREAMING_SERVICE_OVERRIDE_METADATA = "mbms-streaming-service-override";
|
||||
}
|
||||
@@ -1035,6 +1039,17 @@ package android.telephony.mbms.vendor {
|
||||
method public int setTempFileRootDirectory(int, java.lang.String) throws android.os.RemoteException;
|
||||
}
|
||||
|
||||
public class MbmsGroupCallServiceBase extends android.app.Service {
|
||||
ctor public MbmsGroupCallServiceBase();
|
||||
method public void dispose(int) throws android.os.RemoteException;
|
||||
method public int initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int) throws android.os.RemoteException;
|
||||
method public void onAppCallbackDied(int, int);
|
||||
method public android.os.IBinder onBind(android.content.Intent);
|
||||
method public int startGroupCall(int, long, int[], int[], android.telephony.mbms.GroupCallCallback);
|
||||
method public void stopGroupCall(int, long);
|
||||
method public void updateGroupCall(int, long, int[], int[]);
|
||||
}
|
||||
|
||||
public class MbmsStreamingServiceBase extends android.os.Binder {
|
||||
ctor public MbmsStreamingServiceBase();
|
||||
method public void dispose(int) throws android.os.RemoteException;
|
||||
|
||||
300
telephony/java/android/telephony/MbmsGroupCallSession.java
Normal file
300
telephony/java/android/telephony/MbmsGroupCallSession.java
Normal file
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SystemApi;
|
||||
import android.annotation.TestApi;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.telephony.mbms.GroupCall;
|
||||
import android.telephony.mbms.GroupCallCallback;
|
||||
import android.telephony.mbms.InternalGroupCallCallback;
|
||||
import android.telephony.mbms.InternalGroupCallSessionCallback;
|
||||
import android.telephony.mbms.MbmsErrors;
|
||||
import android.telephony.mbms.MbmsGroupCallSessionCallback;
|
||||
import android.telephony.mbms.MbmsUtils;
|
||||
import android.telephony.mbms.vendor.IMbmsGroupCallService;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* This class provides functionality for accessing group call functionality over MBMS.
|
||||
*/
|
||||
public class MbmsGroupCallSession implements AutoCloseable {
|
||||
private static final String LOG_TAG = "MbmsGroupCallSession";
|
||||
|
||||
/**
|
||||
* Service action which must be handled by the middleware implementing the MBMS group call
|
||||
* interface.
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
|
||||
public static final String MBMS_GROUP_CALL_SERVICE_ACTION =
|
||||
"android.telephony.action.EmbmsGroupCall";
|
||||
|
||||
/**
|
||||
* Metadata key that specifies the component name of the service to bind to for group calls.
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public static final String MBMS_GROUP_CALL_SERVICE_OVERRIDE_METADATA =
|
||||
"mbms-group-call-service-override";
|
||||
|
||||
private static AtomicBoolean sIsInitialized = new AtomicBoolean(false);
|
||||
|
||||
private AtomicReference<IMbmsGroupCallService> mService = new AtomicReference<>(null);
|
||||
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
|
||||
@Override
|
||||
public void binderDied() {
|
||||
sIsInitialized.set(false);
|
||||
mInternalCallback.onError(MbmsErrors.ERROR_MIDDLEWARE_LOST,
|
||||
"Received death notification");
|
||||
}
|
||||
};
|
||||
|
||||
private InternalGroupCallSessionCallback mInternalCallback;
|
||||
private Set<GroupCall> mKnownActiveGroupCalls = new ArraySet<>();
|
||||
|
||||
private final Context mContext;
|
||||
private int mSubscriptionId;
|
||||
|
||||
/** @hide */
|
||||
private MbmsGroupCallSession(Context context, Executor executor, int subscriptionId,
|
||||
MbmsGroupCallSessionCallback callback) {
|
||||
mContext = context;
|
||||
mSubscriptionId = subscriptionId;
|
||||
mInternalCallback = new InternalGroupCallSessionCallback(callback, executor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link MbmsGroupCallSession} using the given subscription ID.
|
||||
*
|
||||
* You may only have one instance of {@link MbmsGroupCallSession} per UID. If you call this
|
||||
* method while there is an active instance of {@link MbmsGroupCallSession} in your process
|
||||
* (in other words, one that has not had {@link #close()} called on it), this method will
|
||||
* throw an {@link IllegalStateException}. If you call this method in a different process
|
||||
* running under the same UID, an error will be indicated via
|
||||
* {@link MbmsGroupCallSessionCallback#onError(int, String)}.
|
||||
*
|
||||
* Note that initialization may fail asynchronously. If you wish to try again after you
|
||||
* receive such an asynchronous error, you must call {@link #close()} on the instance of
|
||||
* {@link MbmsGroupCallSession} that you received before calling this method again.
|
||||
*
|
||||
* @param context The {@link Context} to use.
|
||||
* @param executor The executor on which you wish to execute callbacks.
|
||||
* @param subscriptionId The subscription ID to use.
|
||||
* @param callback A callback object on which you wish to receive results of asynchronous
|
||||
* operations.
|
||||
* @return An instance of {@link MbmsGroupCallSession}, or null if an error occurred.
|
||||
*/
|
||||
public static @Nullable MbmsGroupCallSession create(@NonNull Context context,
|
||||
@NonNull Executor executor, int subscriptionId,
|
||||
final @NonNull MbmsGroupCallSessionCallback callback) {
|
||||
if (!sIsInitialized.compareAndSet(false, true)) {
|
||||
throw new IllegalStateException("Cannot create two instances of MbmsGroupCallSession");
|
||||
}
|
||||
MbmsGroupCallSession session = new MbmsGroupCallSession(context, executor,
|
||||
subscriptionId, callback);
|
||||
|
||||
final int result = session.bindAndInitialize();
|
||||
if (result != MbmsErrors.SUCCESS) {
|
||||
sIsInitialized.set(false);
|
||||
executor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onError(result, null);
|
||||
}
|
||||
});
|
||||
return null;
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link MbmsGroupCallSession} using the system default data subscription ID.
|
||||
* See {@link #create(Context, Executor, int, MbmsGroupCallSessionCallback)}.
|
||||
*/
|
||||
public static MbmsGroupCallSession create(@NonNull Context context,
|
||||
@NonNull Executor executor, @NonNull MbmsGroupCallSessionCallback callback) {
|
||||
return create(context, executor, SubscriptionManager.getDefaultSubscriptionId(), callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates this instance. Also terminates
|
||||
* any group calls spawned from this instance as if
|
||||
* {@link GroupCall#close()} had been called on them. After this method returns,
|
||||
* no further callbacks originating from the middleware will be enqueued on the provided
|
||||
* instance of {@link MbmsGroupCallSessionCallback}, but callbacks that have already been
|
||||
* enqueued will still be delivered.
|
||||
*
|
||||
* It is safe to call {@link #create(Context, Executor, int, MbmsGroupCallSessionCallback)} to
|
||||
* obtain another instance of {@link MbmsGroupCallSession} immediately after this method
|
||||
* returns.
|
||||
*
|
||||
* May throw an {@link IllegalStateException}
|
||||
*/
|
||||
public void close() {
|
||||
try {
|
||||
IMbmsGroupCallService groupCallService = mService.get();
|
||||
if (groupCallService == null) {
|
||||
// Ignore and return, assume already disposed.
|
||||
return;
|
||||
}
|
||||
groupCallService.dispose(mSubscriptionId);
|
||||
for (GroupCall s : mKnownActiveGroupCalls) {
|
||||
s.getCallback().stop();
|
||||
}
|
||||
mKnownActiveGroupCalls.clear();
|
||||
} catch (RemoteException e) {
|
||||
// Ignore for now
|
||||
} finally {
|
||||
mService.set(null);
|
||||
sIsInitialized.set(false);
|
||||
mInternalCallback.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the requested group call, reporting status to the indicated callback.
|
||||
* Returns an object used to control that call.
|
||||
*
|
||||
* May throw an {@link IllegalArgumentException} or an {@link IllegalStateException}
|
||||
*
|
||||
* Asynchronous errors through the callback include any of the errors in
|
||||
* {@link MbmsErrors.GeneralErrors}.
|
||||
*
|
||||
* @param executor The executor on which you wish to execute callbacks for this stream.
|
||||
* @param tmgi The TMGI, an identifier for the group call you want to join.
|
||||
* @param saiArray An array of SAIs for the group call that should be negotiated separately with
|
||||
* the carrier.
|
||||
* @param frequencyArray An array of frequencies for the group call that should be negotiated
|
||||
* separately with the carrier.
|
||||
* @param callback The callback that you want to receive information about the call on.
|
||||
* @return An instance of {@link GroupCall} through which the call can be controlled.
|
||||
* May be {@code null} if an error occurred.
|
||||
*/
|
||||
public @Nullable GroupCall startGroupCall(@NonNull Executor executor, long tmgi, int[] saiArray,
|
||||
int[] frequencyArray, @NonNull GroupCallCallback callback) {
|
||||
IMbmsGroupCallService groupCallService = mService.get();
|
||||
if (groupCallService == null) {
|
||||
throw new IllegalStateException("Middleware not yet bound");
|
||||
}
|
||||
|
||||
InternalGroupCallCallback serviceCallback = new InternalGroupCallCallback(
|
||||
callback, executor);
|
||||
|
||||
GroupCall serviceForApp = new GroupCall(mSubscriptionId,
|
||||
groupCallService, this, tmgi, serviceCallback);
|
||||
mKnownActiveGroupCalls.add(serviceForApp);
|
||||
|
||||
try {
|
||||
int returnCode = groupCallService.startGroupCall(
|
||||
mSubscriptionId, tmgi, saiArray, frequencyArray, serviceCallback);
|
||||
if (returnCode == MbmsErrors.UNKNOWN) {
|
||||
// Unbind and throw an obvious error
|
||||
close();
|
||||
throw new IllegalStateException("Middleware must not return an unknown error code");
|
||||
}
|
||||
if (returnCode != MbmsErrors.SUCCESS) {
|
||||
mInternalCallback.onError(returnCode, null);
|
||||
return null;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.w(LOG_TAG, "Remote process died");
|
||||
mService.set(null);
|
||||
sIsInitialized.set(false);
|
||||
mInternalCallback.onError(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
return serviceForApp;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void onGroupCallStopped(GroupCall service) {
|
||||
mKnownActiveGroupCalls.remove(service);
|
||||
}
|
||||
|
||||
private int bindAndInitialize() {
|
||||
return MbmsUtils.startBinding(mContext, MBMS_GROUP_CALL_SERVICE_ACTION,
|
||||
new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
IMbmsGroupCallService groupCallService =
|
||||
IMbmsGroupCallService.Stub.asInterface(service);
|
||||
int result;
|
||||
try {
|
||||
result = groupCallService.initialize(mInternalCallback,
|
||||
mSubscriptionId);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(LOG_TAG, "Service died before initialization");
|
||||
mInternalCallback.onError(
|
||||
MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
|
||||
e.toString());
|
||||
sIsInitialized.set(false);
|
||||
return;
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(LOG_TAG, "Runtime exception during initialization");
|
||||
mInternalCallback.onError(
|
||||
MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
|
||||
e.toString());
|
||||
sIsInitialized.set(false);
|
||||
return;
|
||||
}
|
||||
if (result == MbmsErrors.UNKNOWN) {
|
||||
// Unbind and throw an obvious error
|
||||
close();
|
||||
throw new IllegalStateException("Middleware must not return"
|
||||
+ " an unknown error code");
|
||||
}
|
||||
if (result != MbmsErrors.SUCCESS) {
|
||||
mInternalCallback.onError(result,
|
||||
"Error returned during initialization");
|
||||
sIsInitialized.set(false);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
groupCallService.asBinder().linkToDeath(mDeathRecipient, 0);
|
||||
} catch (RemoteException e) {
|
||||
mInternalCallback.onError(MbmsErrors.ERROR_MIDDLEWARE_LOST,
|
||||
"Middleware lost during initialization");
|
||||
sIsInitialized.set(false);
|
||||
return;
|
||||
}
|
||||
mService.set(groupCallService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
sIsInitialized.set(false);
|
||||
mService.set(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
176
telephony/java/android/telephony/mbms/GroupCall.java
Normal file
176
telephony/java/android/telephony/mbms/GroupCall.java
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.os.RemoteException;
|
||||
import android.telephony.MbmsGroupCallSession;
|
||||
import android.telephony.mbms.vendor.IMbmsGroupCallService;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Class used to represent a single MBMS group call. After a call has been started with
|
||||
* {@link MbmsGroupCallSession#startGroupCall},
|
||||
* this class is used to hold information about the call and control it.
|
||||
*/
|
||||
public class GroupCall implements AutoCloseable {
|
||||
private static final String LOG_TAG = "MbmsGroupCall";
|
||||
|
||||
/**
|
||||
* The state of a group call, reported via
|
||||
* {@link GroupCallCallback#onGroupCallStateChanged(int, int)}
|
||||
* @hide
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(prefix = { "STATE_" }, value = {STATE_STOPPED, STATE_STARTED, STATE_STALLED})
|
||||
public @interface GroupCallState {}
|
||||
public static final int STATE_STOPPED = 1;
|
||||
public static final int STATE_STARTED = 2;
|
||||
public static final int STATE_STALLED = 3;
|
||||
|
||||
/**
|
||||
* The reason for a call state change, reported via
|
||||
* {@link GroupCallCallback#onGroupCallStateChanged(int, int)}
|
||||
* @hide
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(prefix = { "REASON_" },
|
||||
value = {REASON_BY_USER_REQUEST, REASON_FREQUENCY_CONFLICT,
|
||||
REASON_OUT_OF_MEMORY, REASON_NOT_CONNECTED_TO_HOMECARRIER_LTE,
|
||||
REASON_LEFT_MBMS_BROADCAST_AREA, REASON_NONE})
|
||||
public @interface GroupCallStateChangeReason {}
|
||||
|
||||
/**
|
||||
* Indicates that the middleware does not have a reason to provide for the state change.
|
||||
*/
|
||||
public static final int REASON_NONE = 0;
|
||||
|
||||
/**
|
||||
* State changed due to a call to {@link #close()} or
|
||||
* {@link MbmsGroupCallSession#startGroupCall}
|
||||
*/
|
||||
public static final int REASON_BY_USER_REQUEST = 1;
|
||||
|
||||
// 2 is unused to match up with streaming.
|
||||
|
||||
/**
|
||||
* State changed due to a frequency conflict with another requested call.
|
||||
*/
|
||||
public static final int REASON_FREQUENCY_CONFLICT = 3;
|
||||
|
||||
/**
|
||||
* State changed due to the middleware running out of memory
|
||||
*/
|
||||
public static final int REASON_OUT_OF_MEMORY = 4;
|
||||
|
||||
/**
|
||||
* State changed due to the device leaving the home carrier's LTE network.
|
||||
*/
|
||||
public static final int REASON_NOT_CONNECTED_TO_HOMECARRIER_LTE = 5;
|
||||
|
||||
/**
|
||||
* State changed due to the device leaving the area where this call is being broadcast.
|
||||
*/
|
||||
public static final int REASON_LEFT_MBMS_BROADCAST_AREA = 6;
|
||||
|
||||
private final int mSubscriptionId;
|
||||
private final long mTmgi;
|
||||
private final MbmsGroupCallSession mParentSession;
|
||||
private final InternalGroupCallCallback mCallback;
|
||||
private IMbmsGroupCallService mService;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public GroupCall(int subscriptionId,
|
||||
IMbmsGroupCallService service,
|
||||
MbmsGroupCallSession session,
|
||||
long tmgi,
|
||||
InternalGroupCallCallback callback) {
|
||||
mSubscriptionId = subscriptionId;
|
||||
mParentSession = session;
|
||||
mService = service;
|
||||
mTmgi = tmgi;
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the TMGI (Temporary Mobile Group Identity) corresponding to this call.
|
||||
*/
|
||||
public long getTmgi() {
|
||||
return mTmgi;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an update to the middleware when the SAI (Service Area Identifier) list and frequency
|
||||
* information of the group call has * changed. Callers must obtain this information from the
|
||||
* wireless carrier independently.
|
||||
* @param saiArray New array of SAIs that the call is available on.
|
||||
* @param frequencyArray New array of frequencies that the call is available on.
|
||||
*/
|
||||
public void updateGroupCall(int[] saiArray, int[] frequencyArray) {
|
||||
if (mService == null) {
|
||||
throw new IllegalStateException("No group call service attached");
|
||||
}
|
||||
|
||||
try {
|
||||
mService.updateGroupCall(mSubscriptionId, mTmgi, saiArray, frequencyArray);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(LOG_TAG, "Remote process died");
|
||||
mService = null;
|
||||
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||
} finally {
|
||||
mParentSession.onGroupCallStopped(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop this group call. Further operations on this object will fail with an
|
||||
* {@link IllegalStateException}.
|
||||
*
|
||||
* May throw an {@link IllegalStateException}
|
||||
*/
|
||||
@Override
|
||||
public void close() {
|
||||
if (mService == null) {
|
||||
throw new IllegalStateException("No group call service attached");
|
||||
}
|
||||
|
||||
try {
|
||||
mService.stopGroupCall(mSubscriptionId, mTmgi);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(LOG_TAG, "Remote process died");
|
||||
mService = null;
|
||||
sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
|
||||
} finally {
|
||||
mParentSession.onGroupCallStopped(this);
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public InternalGroupCallCallback getCallback() {
|
||||
return mCallback;
|
||||
}
|
||||
|
||||
private void sendErrorToApp(int errorCode, String message) {
|
||||
mCallback.onError(errorCode, message);
|
||||
}
|
||||
}
|
||||
|
||||
87
telephony/java/android/telephony/mbms/GroupCallCallback.java
Normal file
87
telephony/java/android/telephony/mbms/GroupCallCallback.java
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* A callback class for use when the application is in a group call. The middleware
|
||||
* will provide updates on the status of the call via this callback.
|
||||
*/
|
||||
public class GroupCallCallback {
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(value = {
|
||||
MbmsErrors.ERROR_NO_UNIQUE_MIDDLEWARE,
|
||||
MbmsErrors.ERROR_MIDDLEWARE_LOST,
|
||||
MbmsErrors.ERROR_MIDDLEWARE_NOT_BOUND,
|
||||
MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_NOT_YET_READY,
|
||||
MbmsErrors.GeneralErrors.ERROR_OUT_OF_MEMORY,
|
||||
MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE,
|
||||
MbmsErrors.GeneralErrors.ERROR_IN_E911,
|
||||
MbmsErrors.GeneralErrors.ERROR_NOT_CONNECTED_TO_HOME_CARRIER_LTE,
|
||||
MbmsErrors.GeneralErrors.ERROR_UNABLE_TO_READ_SIM,
|
||||
MbmsErrors.GeneralErrors.ERROR_CARRIER_CHANGE_NOT_ALLOWED}, prefix = { "ERROR_" })
|
||||
private @interface GroupCallError{}
|
||||
|
||||
/**
|
||||
* Indicates broadcast signal strength is not available for this call.
|
||||
*
|
||||
* This may be due to the call no longer being available due to geography
|
||||
* or timing (end of service)
|
||||
*/
|
||||
public static final int SIGNAL_STRENGTH_UNAVAILABLE = -1;
|
||||
|
||||
/**
|
||||
* Called by the middleware when it has detected an error condition in this group call. The
|
||||
* possible error codes are listed in {@link MbmsErrors}.
|
||||
* @param errorCode The error code.
|
||||
* @param message A human-readable message generated by the middleware for debugging purposes.
|
||||
*/
|
||||
public void onError(@GroupCallError int errorCode, @Nullable String message) {
|
||||
// default implementation empty
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to indicate this call has changed state.
|
||||
*
|
||||
* See {@link GroupCall#STATE_STOPPED}, {@link GroupCall#STATE_STARTED}
|
||||
* and {@link GroupCall#STATE_STALLED}.
|
||||
*/
|
||||
public void onGroupCallStateChanged(@GroupCall.GroupCallState int state,
|
||||
@GroupCall.GroupCallStateChangeReason int reason) {
|
||||
// default implementation empty
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcast Signal Strength updated.
|
||||
*
|
||||
* This signal strength is the BROADCAST signal strength which,
|
||||
* depending on technology in play and it's deployment, may be
|
||||
* stronger or weaker than the traditional UNICAST signal
|
||||
* strength. It a simple int from 0-4 for valid levels or
|
||||
* {@link #SIGNAL_STRENGTH_UNAVAILABLE} if broadcast is not available
|
||||
* for this call due to timing, geography or popularity.
|
||||
*/
|
||||
public void onBroadcastSignalStrengthUpdated(int signalStrength) {
|
||||
// default implementation empty
|
||||
}
|
||||
}
|
||||
26
telephony/java/android/telephony/mbms/IGroupCallCallback.aidl
Executable file
26
telephony/java/android/telephony/mbms/IGroupCallCallback.aidl
Executable file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
oneway interface IGroupCallCallback {
|
||||
void onError(int errorCode, String message);
|
||||
void onGroupCallStateChanged(int state, int reason);
|
||||
void onBroadcastSignalStrengthUpdated(int signalStrength);
|
||||
}
|
||||
33
telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl
Executable file
33
telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl
Executable file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
** Copyright 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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
oneway interface IMbmsGroupCallSessionCallback
|
||||
{
|
||||
void onError(int errorCode, String message);
|
||||
|
||||
void onAvailableSaisUpdated(in List currentSai, in List availableSais);
|
||||
|
||||
void onServiceInterfaceAvailable(String interfaceName, int index);
|
||||
|
||||
void onMiddlewareReady();
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.os.Binder;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/** @hide */
|
||||
public class InternalGroupCallCallback extends IGroupCallCallback.Stub {
|
||||
private final GroupCallCallback mAppCallback;
|
||||
private final Executor mExecutor;
|
||||
private volatile boolean mIsStopped = false;
|
||||
|
||||
public InternalGroupCallCallback(GroupCallCallback appCallback,
|
||||
Executor executor) {
|
||||
mAppCallback = appCallback;
|
||||
mExecutor = executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final int errorCode, final String message) {
|
||||
if (mIsStopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
mExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mAppCallback.onError(errorCode, message);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGroupCallStateChanged(final int state, final int reason) {
|
||||
if (mIsStopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
mExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mAppCallback.onGroupCallStateChanged(state, reason);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBroadcastSignalStrengthUpdated(final int signalStrength) {
|
||||
if (mIsStopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
mExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mAppCallback.onBroadcastSignalStrengthUpdated(signalStrength);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Prevents this callback from calling the app */
|
||||
public void stop() {
|
||||
mIsStopped = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.os.Binder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/** @hide */
|
||||
public class InternalGroupCallSessionCallback extends IMbmsGroupCallSessionCallback.Stub {
|
||||
private final Executor mExecutor;
|
||||
private final MbmsGroupCallSessionCallback mAppCallback;
|
||||
private volatile boolean mIsStopped = false;
|
||||
|
||||
public InternalGroupCallSessionCallback(MbmsGroupCallSessionCallback appCallback,
|
||||
Executor executor) {
|
||||
mAppCallback = appCallback;
|
||||
mExecutor = executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final int errorCode, final String message) {
|
||||
if (mIsStopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
mExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mAppCallback.onError(errorCode, message);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAvailableSaisUpdated(final List currentSais, final List availableSais) {
|
||||
if (mIsStopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
mExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mAppCallback.onAvailableSaisUpdated(currentSais, availableSais);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceInterfaceAvailable(final String interfaceName, final int index) {
|
||||
if (mIsStopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
mExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mAppCallback.onServiceInterfaceAvailable(interfaceName, index);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMiddlewareReady() {
|
||||
if (mIsStopped) {
|
||||
return;
|
||||
}
|
||||
|
||||
mExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mAppCallback.onMiddlewareReady();
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Prevents this callback from calling the app */
|
||||
public void stop() {
|
||||
mIsStopped = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.telephony.MbmsGroupCallSession;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* A callback class that is used to receive information from the middleware on MBMS group-call
|
||||
* services. An instance of this object should be passed into
|
||||
* {@link MbmsGroupCallSession#create(Context, Executor, int, MbmsGroupCallSessionCallback)}.
|
||||
*/
|
||||
public class MbmsGroupCallSessionCallback {
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(value = {
|
||||
MbmsErrors.ERROR_NO_UNIQUE_MIDDLEWARE,
|
||||
MbmsErrors.ERROR_MIDDLEWARE_LOST,
|
||||
MbmsErrors.ERROR_MIDDLEWARE_NOT_BOUND,
|
||||
MbmsErrors.InitializationErrors.ERROR_APP_PERMISSIONS_NOT_GRANTED,
|
||||
MbmsErrors.InitializationErrors.ERROR_DUPLICATE_INITIALIZE,
|
||||
MbmsErrors.InitializationErrors.ERROR_UNABLE_TO_INITIALIZE,
|
||||
MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_NOT_YET_READY,
|
||||
MbmsErrors.GeneralErrors.ERROR_OUT_OF_MEMORY,
|
||||
MbmsErrors.GeneralErrors.ERROR_MIDDLEWARE_TEMPORARILY_UNAVAILABLE,
|
||||
MbmsErrors.GeneralErrors.ERROR_IN_E911,
|
||||
MbmsErrors.GeneralErrors.ERROR_NOT_CONNECTED_TO_HOME_CARRIER_LTE,
|
||||
MbmsErrors.GeneralErrors.ERROR_UNABLE_TO_READ_SIM,
|
||||
MbmsErrors.GeneralErrors.ERROR_CARRIER_CHANGE_NOT_ALLOWED}, prefix = { "ERROR_" })
|
||||
private @interface GroupCallError{}
|
||||
|
||||
/**
|
||||
* Called by the middleware when it has detected an error condition. The possible error codes
|
||||
* are listed in {@link MbmsErrors}.
|
||||
* @param errorCode The error code.
|
||||
* @param message A human-readable message generated by the middleware for debugging purposes.
|
||||
*/
|
||||
public void onError(@GroupCallError int errorCode, @Nullable String message) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the list of currently available SAIs has been updated. The app may use this
|
||||
* information to filter the list of group calls when displaying available group calls to
|
||||
* the user by matching the SAIs with a list of group calls separately negotiated with the
|
||||
* carrier. The app may also report the aggregate list of SAIs to the group call application
|
||||
* server so that a network entity can determine when, and where to activate the broadcast of
|
||||
* particular group calls.
|
||||
* @param currentSais The available SAIs on the current cell.
|
||||
* @param availableSais A list of lists of available SAIS in neighboring cells, where each list
|
||||
* contains the available SAIs in an individual cell.
|
||||
*/
|
||||
public void onAvailableSaisUpdated(List<Integer> currentSais,
|
||||
List<List<Integer>> availableSais) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called soon after the app calls {@link MbmsGroupCallSession#create}. The information supplied
|
||||
* via this callback may be used to establish a data-link interface with the modem before the
|
||||
* middleware is ready.
|
||||
* Note that this method may be called before {@link #onMiddlewareReady()}.
|
||||
*
|
||||
* @param interfaceName The interface name for the data link.
|
||||
* @param index The index for the data link.
|
||||
*/
|
||||
public void onServiceInterfaceAvailable(String interfaceName, int index) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to indicate that the middleware has been initialized and is ready.
|
||||
*
|
||||
* Before this method is called, calling any method on an instance of
|
||||
* {@link MbmsGroupCallSession} will result in an {@link IllegalStateException} or an error
|
||||
* delivered via {@link #onError(int, String)} with error code
|
||||
* {@link MbmsErrors.GeneralErrors#ERROR_MIDDLEWARE_NOT_YET_READY}.
|
||||
*/
|
||||
public void onMiddlewareReady() {
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import android.content.ServiceConnection;
|
||||
import android.content.pm.*;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.telephony.MbmsDownloadSession;
|
||||
import android.telephony.MbmsGroupCallSession;
|
||||
import android.telephony.MbmsStreamingSession;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -59,6 +60,9 @@ public class MbmsUtils {
|
||||
case MbmsStreamingSession.MBMS_STREAMING_SERVICE_ACTION:
|
||||
metaDataKey = MbmsStreamingSession.MBMS_STREAMING_SERVICE_OVERRIDE_METADATA;
|
||||
break;
|
||||
case MbmsGroupCallSession.MBMS_GROUP_CALL_SERVICE_ACTION:
|
||||
metaDataKey = MbmsGroupCallSession.MBMS_GROUP_CALL_SERVICE_OVERRIDE_METADATA;
|
||||
break;
|
||||
}
|
||||
if (metaDataKey == null) {
|
||||
return null;
|
||||
|
||||
39
telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl
vendored
Executable file
39
telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl
vendored
Executable file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
** Copyright 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.mbms.vendor;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.telephony.mbms.IMbmsGroupCallSessionCallback;
|
||||
import android.telephony.mbms.IGroupCallCallback;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
interface IMbmsGroupCallService
|
||||
{
|
||||
int initialize(IMbmsGroupCallSessionCallback callback, int subId);
|
||||
|
||||
void stopGroupCall(int subId, long tmgi);
|
||||
|
||||
void updateGroupCall(int subscriptionId, long tmgi, in int[] saiArray,
|
||||
in int[] frequencyArray);
|
||||
|
||||
int startGroupCall(int subscriptionId, long tmgi, in int[] saiArray,
|
||||
in int[] frequencyArray, IGroupCallCallback callback);
|
||||
|
||||
void dispose(int subId);
|
||||
}
|
||||
275
telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java
vendored
Normal file
275
telephony/java/android/telephony/mbms/vendor/MbmsGroupCallServiceBase.java
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* 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.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, int[] saiArray,
|
||||
int[] frequencyArray) {
|
||||
MbmsGroupCallServiceBase.this.updateGroupCall(
|
||||
subscriptionId, tmgi, saiArray, frequencyArray);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int startGroupCall(final int subscriptionId, final long tmgi, final int[] saiArray,
|
||||
final int[] frequencyArray, 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, saiArray, frequencyArray, 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.InitializationErrors#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(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 saiArray An array of SAIs for the group call.
|
||||
* @param frequencyArray An array 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, int[] saiArray, int[] frequencyArray,
|
||||
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 saiArray New array of SAIs that the call is available on.
|
||||
* @param frequencyArray New array of frequencies that the call is available on.
|
||||
*/
|
||||
public void updateGroupCall(int subscriptionId, long tmgi, int[] saiArray,
|
||||
int[] frequencyArray) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user