aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad Ebinger <breadley@google.com>2017-11-06 15:17:32 -0800
committerBrad Ebinger <breadley@google.com>2017-11-07 10:02:23 -0800
commit89fb564139a852e8dda966a4945588fe0980123d (patch)
tree380edee3e71373338abde86e45af1623e57468ee
parenta7c3243f07bd2891860fd719f1c21b869f1efc91 (diff)
downloadims-89fb564139a852e8dda966a4945588fe0980123d.tar.gz
Move ImsServiceProxy into this directory
ImsServiceProxy is tightly coupled with the ImsManager and should be in the same namespace. Test: Manual Change-Id: I1383fb114b3c23d2f3d80fa4abdb4b1091c7f879
-rw-r--r--src/java/com/android/ims/ImsManager.java2
-rw-r--r--src/java/com/android/ims/ImsServiceProxy.java348
-rw-r--r--src/java/com/android/ims/ImsServiceProxyCompat.java166
3 files changed, 514 insertions, 2 deletions
diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java
index 7ed0ab52..0e611e4c 100644
--- a/src/java/com/android/ims/ImsManager.java
+++ b/src/java/com/android/ims/ImsManager.java
@@ -37,8 +37,6 @@ import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import android.telephony.ims.ImsServiceProxy;
-import android.telephony.ims.ImsServiceProxyCompat;
import android.telephony.ims.feature.ImsFeature;
import android.util.Log;
diff --git a/src/java/com/android/ims/ImsServiceProxy.java b/src/java/com/android/ims/ImsServiceProxy.java
new file mode 100644
index 00000000..f7fe1d89
--- /dev/null
+++ b/src/java/com/android/ims/ImsServiceProxy.java
@@ -0,0 +1,348 @@
+/*
+ * 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.ims;
+
+import android.app.PendingIntent;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telephony.ims.feature.IMMTelFeature;
+import android.telephony.ims.feature.IRcsFeature;
+import android.telephony.ims.feature.ImsFeature;
+import android.util.Log;
+
+import com.android.ims.internal.IImsCallSession;
+import com.android.ims.internal.IImsCallSessionListener;
+import com.android.ims.internal.IImsConfig;
+import com.android.ims.internal.IImsEcbm;
+import com.android.ims.internal.IImsMultiEndpoint;
+import com.android.ims.internal.IImsRegistrationListener;
+import com.android.ims.internal.IImsServiceController;
+import com.android.ims.internal.IImsServiceFeatureListener;
+import com.android.ims.internal.IImsUt;
+
+/**
+ * A container of the IImsServiceController binder, which implements all of the ImsFeatures that
+ * the platform currently supports: MMTel and RCS.
+ * @hide
+ */
+
+public class ImsServiceProxy implements IMMTelFeature, IRcsFeature {
+
+ protected String LOG_TAG = "ImsServiceProxy";
+ protected final int mSlotId;
+ protected IBinder mBinder;
+ private final int mSupportedFeature;
+
+ // Start by assuming the proxy is available for usage.
+ private boolean mIsAvailable = true;
+ // ImsFeature Status from the ImsService. Cached.
+ private Integer mFeatureStatusCached = null;
+ private ImsServiceProxy.INotifyStatusChanged mStatusCallback;
+ private final Object mLock = new Object();
+
+ public interface INotifyStatusChanged {
+ void notifyStatusChanged();
+ }
+
+ private final IImsServiceFeatureListener mListenerBinder =
+ new IImsServiceFeatureListener.Stub() {
+
+ @Override
+ public void imsFeatureCreated(int slotId, int feature) throws RemoteException {
+ // The feature has been re-enabled. This may happen when the service crashes.
+ synchronized (mLock) {
+ if (!mIsAvailable && mSlotId == slotId && feature == mSupportedFeature) {
+ Log.i(LOG_TAG, "Feature enabled on slotId: " + slotId + " for feature: " +
+ feature);
+ mIsAvailable = true;
+ }
+ }
+ }
+
+ @Override
+ public void imsFeatureRemoved(int slotId, int feature) throws RemoteException {
+ synchronized (mLock) {
+ if (mIsAvailable && mSlotId == slotId && feature == mSupportedFeature) {
+ Log.i(LOG_TAG, "Feature disabled on slotId: " + slotId + " for feature: " +
+ feature);
+ mIsAvailable = false;
+ }
+ }
+ }
+
+ @Override
+ public void imsStatusChanged(int slotId, int feature, int status) throws RemoteException {
+ synchronized (mLock) {
+ Log.i(LOG_TAG, "imsStatusChanged: slot: " + slotId + " feature: " + feature +
+ " status: " + status);
+ if (mSlotId == slotId && feature == mSupportedFeature) {
+ mFeatureStatusCached = status;
+ if (mStatusCallback != null) {
+ mStatusCallback.notifyStatusChanged();
+ }
+ }
+ }
+ }
+ };
+
+ public ImsServiceProxy(int slotId, IBinder binder, int featureType) {
+ mSlotId = slotId;
+ mBinder = binder;
+ mSupportedFeature = featureType;
+ }
+
+ public ImsServiceProxy(int slotId, int featureType) {
+ this(slotId, null, featureType);
+ }
+
+ public IImsServiceFeatureListener getListener() {
+ return mListenerBinder;
+ }
+
+ public void setBinder(IBinder binder) {
+ mBinder = binder;
+ }
+
+ @Override
+ public int startSession(PendingIntent incomingCallIntent, IImsRegistrationListener listener)
+ throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).startSession(mSlotId, mSupportedFeature,
+ incomingCallIntent, listener);
+ }
+ }
+
+ @Override
+ public void endSession(int sessionId) throws RemoteException {
+ synchronized (mLock) {
+ // Only check to make sure the binder connection still exists. This method should
+ // still be able to be called when the state is STATE_NOT_AVAILABLE.
+ checkBinderConnection();
+ getServiceInterface(mBinder).endSession(mSlotId, mSupportedFeature, sessionId);
+ }
+ }
+
+ @Override
+ public boolean isConnected(int callServiceType, int callType)
+ throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).isConnected(mSlotId, mSupportedFeature,
+ callServiceType, callType);
+ }
+ }
+
+ @Override
+ public boolean isOpened() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).isOpened(mSlotId, mSupportedFeature);
+ }
+ }
+
+ @Override
+ public void addRegistrationListener(IImsRegistrationListener listener)
+ throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).addRegistrationListener(mSlotId, mSupportedFeature,
+ listener);
+ }
+ }
+
+ @Override
+ public void removeRegistrationListener(IImsRegistrationListener listener)
+ throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).removeRegistrationListener(mSlotId, mSupportedFeature,
+ listener);
+ }
+ }
+
+ @Override
+ public ImsCallProfile createCallProfile(int sessionId, int callServiceType, int callType)
+ throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).createCallProfile(mSlotId, mSupportedFeature,
+ sessionId, callServiceType, callType);
+ }
+ }
+
+ @Override
+ public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile,
+ IImsCallSessionListener listener) throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).createCallSession(mSlotId, mSupportedFeature,
+ sessionId, profile, listener);
+ }
+ }
+
+ @Override
+ public IImsCallSession getPendingCallSession(int sessionId, String callId)
+ throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).getPendingCallSession(mSlotId, mSupportedFeature,
+ sessionId, callId);
+ }
+ }
+
+ @Override
+ public IImsUt getUtInterface() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).getUtInterface(mSlotId, mSupportedFeature);
+ }
+ }
+
+ @Override
+ public IImsConfig getConfigInterface() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).getConfigInterface(mSlotId, mSupportedFeature);
+ }
+ }
+
+ @Override
+ public void turnOnIms() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).turnOnIms(mSlotId, mSupportedFeature);
+ }
+ }
+
+ @Override
+ public void turnOffIms() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).turnOffIms(mSlotId, mSupportedFeature);
+ }
+ }
+
+ @Override
+ public IImsEcbm getEcbmInterface() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).getEcbmInterface(mSlotId, mSupportedFeature);
+ }
+ }
+
+ @Override
+ public void setUiTTYMode(int uiTtyMode, Message onComplete)
+ throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).setUiTTYMode(mSlotId, mSupportedFeature, uiTtyMode,
+ onComplete);
+ }
+ }
+
+ @Override
+ public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).getMultiEndpointInterface(mSlotId,
+ mSupportedFeature);
+ }
+ }
+
+ /**
+ * @return an integer describing the current Feature Status, defined in
+ * {@link ImsFeature.ImsState}.
+ */
+ public int getFeatureStatus() {
+ synchronized (mLock) {
+ if (isBinderAlive() && mFeatureStatusCached != null) {
+ Log.i(LOG_TAG, "getFeatureStatus - returning cached: " + mFeatureStatusCached);
+ return mFeatureStatusCached;
+ }
+ }
+ // Don't synchronize on Binder call.
+ Integer status = retrieveFeatureStatus();
+ synchronized (mLock) {
+ if (status == null) {
+ return ImsFeature.STATE_NOT_AVAILABLE;
+ }
+ // Cache only non-null value for feature status.
+ mFeatureStatusCached = status;
+ }
+ Log.i(LOG_TAG, "getFeatureStatus - returning " + status);
+ return status;
+ }
+
+ /**
+ * Internal method used to retrieve the feature status from the corresponding ImsService.
+ */
+ private Integer retrieveFeatureStatus() {
+ if (mBinder != null) {
+ try {
+ return getServiceInterface(mBinder).getFeatureStatus(mSlotId, mSupportedFeature);
+ } catch (RemoteException e) {
+ // Status check failed, don't update cache
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @param c Callback that will fire when the feature status has changed.
+ */
+ public void setStatusCallback(INotifyStatusChanged c) {
+ mStatusCallback = c;
+ }
+
+ /**
+ * @return Returns true if the ImsService is ready to take commands, false otherwise. If this
+ * method returns false, it doesn't mean that the Binder connection is not available (use
+ * {@link #isBinderReady()} to check that), but that the ImsService is not accepting commands
+ * at this time.
+ *
+ * For example, for DSDS devices, only one slot can be {@link ImsFeature#STATE_READY} to take
+ * commands at a time, so the other slot must stay at {@link ImsFeature#STATE_NOT_AVAILABLE}.
+ */
+ public boolean isBinderReady() {
+ return isBinderAlive() && getFeatureStatus() == ImsFeature.STATE_READY;
+ }
+
+ /**
+ * @return false if the binder connection is no longer alive.
+ */
+ public boolean isBinderAlive() {
+ return mIsAvailable && mBinder != null && mBinder.isBinderAlive();
+ }
+
+ protected void checkServiceIsReady() throws RemoteException {
+ if (!isBinderReady()) {
+ throw new RemoteException("ImsServiceProxy is not ready to accept commands.");
+ }
+ }
+
+ private IImsServiceController getServiceInterface(IBinder b) {
+ return IImsServiceController.Stub.asInterface(b);
+ }
+
+ protected void checkBinderConnection() throws RemoteException {
+ if (!isBinderAlive()) {
+ throw new RemoteException("ImsServiceProxy is not available for that feature.");
+ }
+ }
+}
diff --git a/src/java/com/android/ims/ImsServiceProxyCompat.java b/src/java/com/android/ims/ImsServiceProxyCompat.java
new file mode 100644
index 00000000..a96446ad
--- /dev/null
+++ b/src/java/com/android/ims/ImsServiceProxyCompat.java
@@ -0,0 +1,166 @@
+/*
+ * 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.ims;
+
+import android.app.PendingIntent;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telephony.ims.feature.ImsFeature;
+
+import com.android.ims.internal.IImsCallSession;
+import com.android.ims.internal.IImsCallSessionListener;
+import com.android.ims.internal.IImsConfig;
+import com.android.ims.internal.IImsEcbm;
+import com.android.ims.internal.IImsMultiEndpoint;
+import com.android.ims.internal.IImsRegistrationListener;
+import com.android.ims.internal.IImsService;
+import com.android.ims.internal.IImsUt;
+
+/**
+ * Compatibility class that implements the new ImsService IMMTelFeature interface, but
+ * uses the old IImsService interface to support older devices that implement the deprecated
+ * opt/net/ims interface.
+ * @hide
+ */
+
+public class ImsServiceProxyCompat extends ImsServiceProxy {
+
+ private static final int SERVICE_ID = ImsFeature.MMTEL;
+
+ public ImsServiceProxyCompat(int slotId, IBinder binder) {
+ super(slotId, binder, SERVICE_ID);
+ }
+
+ @Override
+ public int startSession(PendingIntent incomingCallIntent, IImsRegistrationListener listener)
+ throws RemoteException {
+ checkBinderConnection();
+ return getServiceInterface(mBinder).open(mSlotId, ImsFeature.MMTEL, incomingCallIntent,
+ listener);
+ }
+
+ @Override
+ public void endSession(int sessionId) throws RemoteException {
+ checkBinderConnection();
+ getServiceInterface(mBinder).close(sessionId);
+ }
+
+ @Override
+ public boolean isConnected(int callServiceType, int callType)
+ throws RemoteException {
+ checkBinderConnection();
+ return getServiceInterface(mBinder).isConnected(SERVICE_ID, callServiceType, callType);
+ }
+
+ @Override
+ public boolean isOpened() throws RemoteException {
+ checkBinderConnection();
+ return getServiceInterface(mBinder).isOpened(SERVICE_ID);
+ }
+
+ @Override
+ public void addRegistrationListener(IImsRegistrationListener listener)
+ throws RemoteException {
+ checkBinderConnection();
+ getServiceInterface(mBinder).addRegistrationListener(mSlotId, ImsFeature.MMTEL, listener);
+ }
+
+ @Override
+ public void removeRegistrationListener(IImsRegistrationListener listener)
+ throws RemoteException {
+ // Not Implemented in old ImsService. If the registration listener becomes invalid, the
+ // ImsService will remove.
+ }
+
+ @Override
+ public ImsCallProfile createCallProfile(int sessionId, int callServiceType, int callType)
+ throws RemoteException {
+ checkBinderConnection();
+ return getServiceInterface(mBinder).createCallProfile(sessionId, callServiceType, callType);
+ }
+
+ @Override
+ public IImsCallSession createCallSession(int sessionId, ImsCallProfile profile,
+ IImsCallSessionListener listener) throws RemoteException {
+ checkBinderConnection();
+ return getServiceInterface(mBinder).createCallSession(sessionId, profile, listener);
+ }
+
+ @Override
+ public IImsCallSession getPendingCallSession(int sessionId, String callId)
+ throws RemoteException {
+ checkBinderConnection();
+ return getServiceInterface(mBinder).getPendingCallSession(sessionId, callId);
+ }
+
+ @Override
+ public IImsUt getUtInterface() throws RemoteException {
+ checkBinderConnection();
+ return getServiceInterface(mBinder).getUtInterface(SERVICE_ID);
+ }
+
+ @Override
+ public IImsConfig getConfigInterface() throws RemoteException {
+ checkBinderConnection();
+ return getServiceInterface(mBinder).getConfigInterface(mSlotId);
+ }
+
+ @Override
+ public void turnOnIms() throws RemoteException {
+ checkBinderConnection();
+ getServiceInterface(mBinder).turnOnIms(mSlotId);
+ }
+
+ @Override
+ public void turnOffIms() throws RemoteException {
+ checkBinderConnection();
+ getServiceInterface(mBinder).turnOffIms(mSlotId);
+ }
+
+ @Override
+ public IImsEcbm getEcbmInterface() throws RemoteException {
+ checkBinderConnection();
+ return getServiceInterface(mBinder).getEcbmInterface(SERVICE_ID);
+ }
+
+ @Override
+ public void setUiTTYMode(int uiTtyMode, Message onComplete)
+ throws RemoteException {
+ checkBinderConnection();
+ getServiceInterface(mBinder).setUiTTYMode(SERVICE_ID, uiTtyMode, onComplete);
+ }
+
+ @Override
+ public IImsMultiEndpoint getMultiEndpointInterface() throws RemoteException {
+ checkBinderConnection();
+ return getServiceInterface(mBinder).getMultiEndpointInterface(SERVICE_ID);
+ }
+ @Override
+ public int getFeatureStatus() {
+ return ImsFeature.STATE_READY;
+ }
+
+ @Override
+ public boolean isBinderAlive() {
+ return mBinder != null && mBinder.isBinderAlive();
+ }
+
+ private IImsService getServiceInterface(IBinder b) {
+ return IImsService.Stub.asInterface(b);
+ }
+}