diff options
author | Brad Ebinger <breadley@google.com> | 2017-11-08 17:21:57 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-11-08 17:21:57 +0000 |
commit | bfd53105cd71fc569a99c3a11d4015def4f4758c (patch) | |
tree | 380edee3e71373338abde86e45af1623e57468ee | |
parent | 8b6fa79cdbc5171320555fe6f96e0e0de20cd5f1 (diff) | |
parent | 89fb564139a852e8dda966a4945588fe0980123d (diff) | |
download | ims-bfd53105cd71fc569a99c3a11d4015def4f4758c.tar.gz |
Move ImsServiceProxy into this directory
am: 89fb564139
Change-Id: I1b66d3a73f9d5725f0a7e21436daa1c948691c91
-rw-r--r-- | src/java/com/android/ims/ImsManager.java | 2 | ||||
-rw-r--r-- | src/java/com/android/ims/ImsServiceProxy.java | 348 | ||||
-rw-r--r-- | src/java/com/android/ims/ImsServiceProxyCompat.java | 166 |
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); + } +} |