summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--rcs/rcsmanager/src/java/com/android/ims/RcsManager.java10
-rw-r--r--rcs/rcsservice/Android.bp3
-rw-r--r--rcs/rcsservice/AndroidManifest.xml12
-rw-r--r--rcs/rcsservice/src/com/android/service/ims/ImsServiceImpl.java105
-rw-r--r--rcs/rcsservice/src/com/android/service/ims/RcsFeatureImpl.java373
-rw-r--r--rcs/rcsservice/src/com/android/service/ims/RcsPresenceExchangeImpl.java124
-rw-r--r--rcs/rcsservice/src/com/android/service/ims/RcsService.java2
-rw-r--r--rcs/rcsservice/src/com/android/service/ims/RcsServiceApp.java2
-rw-r--r--rcs/rcsservice/src/com/android/service/ims/RcsStackAdaptor.java20
-rw-r--r--rcs/rcsservice/src/com/android/service/ims/RcsUtils.java78
-rw-r--r--rcs/rcsservice/src/com/android/service/ims/TaskManager.java15
-rw-r--r--rcs/rcsservice/src/com/android/service/ims/presence/PresencePublication.java110
-rw-r--r--rcs/rcsservice/src/com/android/service/ims/presence/PresenceSubscriber.java95
-rw-r--r--rcs/rcsservice/src/com/android/service/ims/presence/StackListener.java42
14 files changed, 901 insertions, 90 deletions
diff --git a/rcs/rcsmanager/src/java/com/android/ims/RcsManager.java b/rcs/rcsmanager/src/java/com/android/ims/RcsManager.java
index 644d567..c198bb3 100644
--- a/rcs/rcsmanager/src/java/com/android/ims/RcsManager.java
+++ b/rcs/rcsmanager/src/java/com/android/ims/RcsManager.java
@@ -239,6 +239,7 @@ public class RcsManager {
private int mSubId;
private IRcsService mRcsService = null;
private RcsServiceDeathRecipient mDeathRecipient = new RcsServiceDeathRecipient();
+ private boolean mPresenceEnabledByFramework = true;
// Interface for presence
// TODO: Could add other RCS service such RcsChat, RcsFt later.
@@ -290,8 +291,9 @@ public class RcsManager {
Rlog.e(TAG, "isRcsServiceAvailable RcsException", e);
}
- if (DBG) Rlog.d(TAG, "isRcsServiceAvailable ret =" + ret);
- return ret;
+ if (DBG) Rlog.d(TAG, "isRcsServiceAvailable ret =" + ret + " mPresenceEnabledByFramework ="
+ + mPresenceEnabledByFramework);
+ return ret && mPresenceEnabledByFramework;
}
/**
@@ -381,4 +383,8 @@ public class RcsManager {
}
}
}
+
+ public void setPresenceEnabledByFramework(boolean presenceEnabledByFramework) {
+ mPresenceEnabledByFramework = presenceEnabledByFramework;
+ }
}
diff --git a/rcs/rcsservice/Android.bp b/rcs/rcsservice/Android.bp
index 24153a5..547ae5e 100644
--- a/rcs/rcsservice/Android.bp
+++ b/rcs/rcsservice/Android.bp
@@ -38,6 +38,9 @@ java_library {
"src/com/android/service/ims/RcsUtils.java",
"src/com/android/service/ims/Task.java",
"src/com/android/service/ims/TaskManager.java",
+ "src/com/android/service/ims/RcsFeatureImpl.java",
+ "src/com/android/service/ims/RcsPresenceExchangeImpl.java",
+ "src/com/android/service/ims/ImsServiceImpl.java",
// Move the following to the app once the dependencies have been decoupled.
"src/com/android/service/ims/RcsStackAdaptor.java"
],
diff --git a/rcs/rcsservice/AndroidManifest.xml b/rcs/rcsservice/AndroidManifest.xml
index 9b9de40..0f31c7b 100644
--- a/rcs/rcsservice/AndroidManifest.xml
+++ b/rcs/rcsservice/AndroidManifest.xml
@@ -56,12 +56,22 @@
<uses-permission android:name="com.android.rcs.eab.permission.READ_WRITE_EAB"/>
<application android:name="RcsServiceApp" android:persistent="true"
- android:process="com.android.ims.rcsservice">
+ android:process="com.android.ims.rcsservice" android:directBootAware="true">
<service android:name="com.android.service.ims.RcsService"
android:exported="true"
android:enabled="true"
android:permission="com.android.ims.permission.PRESENCE_ACCESS">
</service>
+ <service
+ android:name="com.android.service.ims.ImsServiceImpl"
+ android:persistent="true"
+ android:permission="android.permission.BIND_IMS_SERVICE" >
+ <meta-data android:name="android.telephony.ims.RCS_FEATURE" android:value="true" />
+ <intent-filter>
+ <action android:name="android.telephony.ims.ImsService" />
+ </intent-filter>
+ </service>
+
<receiver android:name="com.android.service.ims.DeviceShutdown"
androidprv:systemUserOnly="true">
diff --git a/rcs/rcsservice/src/com/android/service/ims/ImsServiceImpl.java b/rcs/rcsservice/src/com/android/service/ims/ImsServiceImpl.java
new file mode 100644
index 0000000..8f4948c
--- /dev/null
+++ b/rcs/rcsservice/src/com/android/service/ims/ImsServiceImpl.java
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.android.service.ims;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.telephony.TelephonyManager;
+import android.telephony.ims.ImsService;
+import android.telephony.ims.feature.RcsFeature;
+import android.util.Log;
+
+public class ImsServiceImpl extends ImsService {
+ public static final String TAG = "ImsServiceImpl";
+ private static final int INVALID_SLOT_ID = -1;
+ private static final int UNINITIALIZED_VALUE = -1;
+ private int mNumPhonesCache = UNINITIALIZED_VALUE;
+ private RcsFeature mRcsFeature[];
+ protected final Object mLock = new Object();
+
+ private int getNumSlots() {
+ if (mNumPhonesCache == UNINITIALIZED_VALUE) {
+ mNumPhonesCache = ((TelephonyManager) getSystemService(
+ Context.TELEPHONY_SERVICE)).getPhoneCount();
+ }
+ return mNumPhonesCache;
+ }
+
+ private void setup() {
+ final int numSlots = getNumSlots();
+ mRcsFeature = new RcsFeatureImpl[numSlots];
+ for (int i = 0; i < numSlots; i++) {
+ mRcsFeature[i] = new RcsFeatureImpl(this, i);
+ }
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ Log.i(TAG, "ImsService created!");
+ setup();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ if (android.telephony.ims.ImsService.SERVICE_INTERFACE.equals(intent.getAction())) {
+ Log.d(TAG, "Returning mImsServiceController for ImsService binding");
+ return mImsServiceController;
+ }
+ Log.e(TAG, "Invalid Intent action in onBind: " + intent.getAction());
+ return null;
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ Log.i(TAG, "ImsService destroyed!");
+ }
+
+ /**
+ * When called, the framework is requesting that a new {@link RcsFeature} is created for the
+ * specified slot.
+ *
+ * @param slotId The slot ID that the RCS Feature is being created for.
+ * @return The newly created {@link RcsFeature} associated with the slot or null if the feature
+ * is not supported.
+ */
+ @Override
+ public RcsFeature createRcsFeature(int slotId) {
+ Log.d(TAG, "createRcsFeature :: slotId=" + slotId + " numSlots=" + mNumPhonesCache);
+ if (slotId > INVALID_SLOT_ID && slotId < getNumSlots()) {
+ return mRcsFeature[slotId];
+ }
+ Log.e(TAG, "createRcsFeature :: Invalid slotId " + slotId);
+ return null;
+ }
+}
diff --git a/rcs/rcsservice/src/com/android/service/ims/RcsFeatureImpl.java b/rcs/rcsservice/src/com/android/service/ims/RcsFeatureImpl.java
new file mode 100644
index 0000000..53c44ad
--- /dev/null
+++ b/rcs/rcsservice/src/com/android/service/ims/RcsFeatureImpl.java
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+package com.android.service.ims;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.telephony.SubscriptionManager;
+import android.telephony.ims.feature.CapabilityChangeRequest;
+import android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair;
+import android.telephony.ims.feature.ImsFeature;
+import android.telephony.ims.feature.RcsFeature;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.telephony.ims.stub.RcsPresenceExchangeImplBase;
+import android.telephony.ims.stub.RcsSipOptionsImplBase;
+import android.util.Log;
+
+import com.android.ims.RcsManager;
+import com.android.internal.telephony.TelephonyIntents;
+
+import java.util.List;
+
+public class RcsFeatureImpl extends RcsFeature {
+
+ private static final String TAG = "RcsFeatureImpl";
+
+ private static final String RCS_PACKAGE = "com.android.service.ims";
+ private static final String RCS_CLASS = "com.android.service.ims.RcsService";
+ private Context mContext;
+ private Handler mFeatureCallbackHandler;
+ private HandlerThread mFeatureHandlerThread;
+ private RcsImsCapabilities mRcsImsCapabilities;
+ private int mPhoneId;
+ private int mSubId;
+ private int mDefaultVoiceSubId;
+ private SubscriptionManager mSubscriptionManager;
+ private SubscriptionChangedListener mSubscriptionListener;
+ private RcsPresenceExchangeImplBase mRcsPresenceExchangeBase;
+ private RcsStackAdaptor mRcsStackAdaptor;
+
+ // Used to synchronize mSubId and mDefaultVoiceSubId
+ private Object mToken = new Object();
+
+
+ public RcsFeatureImpl(Context context, int phoneId) {
+ mContext = context;
+ mPhoneId = phoneId;
+ mFeatureHandlerThread = new HandlerThread(this + "FeatureHandlerThread");
+ mFeatureHandlerThread.start();
+ mFeatureCallbackHandler = new Handler(mFeatureHandlerThread.getLooper());
+ mDefaultVoiceSubId = SubscriptionManager.getDefaultSubscriptionId();
+ mRcsPresenceExchangeBase = new RcsPresenceExchangeImpl(mContext);
+ mRcsStackAdaptor = RcsStackAdaptor.getInstance(mContext);
+ mRcsImsCapabilities = new RcsImsCapabilities(RcsImsCapabilities.CAPABILITY_TYPE_NONE);
+ mSubscriptionManager = (SubscriptionManager) mContext.getSystemService(
+ Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ mSubId = getSubId();
+ mSubscriptionListener = new SubscriptionChangedListener();
+ mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
+
+ registerVoiceSubscriptionChange();
+ registerRcsStateReceiver();
+ initFeatureState();
+ logd("RcsFeatureImpl constructor mSubId:" + mSubId + ", "
+ + "mDefaultVoiceSubId:" + mDefaultVoiceSubId);
+
+ }
+
+ private int getSubId() {
+ int subId[] = mSubscriptionManager.getSubscriptionIds(mPhoneId);
+ return subId != null ? subId[0] : SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ }
+
+ private void registerVoiceSubscriptionChange() {
+ IntentFilter intentFilter = new IntentFilter
+ (TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
+ mContext.registerReceiver(mVoiceSubscriptionReceiver, intentFilter);
+ }
+
+ private void initFeatureState() {
+ // In DSDS environment, RcsFeatureImpl is only available for default voice subId.
+ if (isDefaultVoiceSubId()) {
+ logd("set STATE_READY");
+ setFeatureState(ImsFeature.STATE_READY);
+ } else {
+ logd("set STATE_UNAVAILABLE");
+ setFeatureState(ImsFeature.STATE_UNAVAILABLE);
+ }
+ }
+
+ private boolean isDefaultVoiceSubId() {
+ synchronized (mToken) {
+ return SubscriptionManager.isValidSubscriptionId(mSubId) &&
+ SubscriptionManager.isValidSubscriptionId(mDefaultVoiceSubId) &&
+ mSubscriptionManager.isActiveSubscriptionId(mSubId) &&
+ mSubscriptionManager.isActiveSubscriptionId(mDefaultVoiceSubId) &&
+ mSubId == mDefaultVoiceSubId;
+ }
+ }
+
+ private void startRcsService() {
+ ComponentName comp = new ComponentName(RCS_PACKAGE, RCS_CLASS);
+ ComponentName service = mContext.startService(new Intent().setComponent(comp));
+ if (service == null) {
+ Log.e(TAG, "Could Not Start Service " + comp.toString());
+ } else {
+ Log.d(TAG, comp.toString() + " started Successfully");
+ }
+ }
+
+ @Override
+ public void onFeatureReady() {
+ logd("onFeatureReady");
+ mRcsPresenceExchangeBase.initialize(this);
+ mRcsStackAdaptor.setRcsPresenceExchangeImplBase(mRcsPresenceExchangeBase);
+ mRcsStackAdaptor.init();
+ startRcsService();
+ }
+
+ @Override
+ public void onFeatureRemoved() {
+ logd("onFeatureRemoved");
+ mContext.unregisterReceiver(mRcsStateReceiver);
+ mContext.unregisterReceiver(mVoiceSubscriptionReceiver);
+ mRcsStackAdaptor.setRcsPresenceExchangeImplBase(null);
+ }
+
+ private void registerRcsStateReceiver() {
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(RcsManager.ACTION_RCS_SERVICE_AVAILABLE);
+ intentFilter.addAction(RcsManager.ACTION_RCS_SERVICE_UNAVAILABLE);
+ intentFilter.addAction(RcsManager.ACTION_RCS_SERVICE_DIED);
+ mContext.registerReceiver(mRcsStateReceiver, intentFilter);
+ }
+
+ /**
+ * Retrieve the implementation of UCE presence for this {@link RcsFeature}.
+ * Will only be requested by the framework if presence exchang is configured as capable during
+ * a {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}
+ * operation and the RcsFeature sets the status of the capability to true using
+ * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}.
+ *
+ * @return An instance of {@link RcsPresenceExchangeImplBase} that implements presence
+ * exchange if it is supported by the device.
+ * @hide
+ */
+ @Override
+ public RcsPresenceExchangeImplBase getPresenceExchangeImpl() {
+ return mRcsPresenceExchangeBase;
+ }
+
+ /**
+ * Retrieve the implementation of SIP OPTIONS for this {@link RcsFeature}.
+ * <p>
+ * Will only be requested by the framework if capability exchange via SIP OPTIONS is
+ * configured as capable during a
+ * {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}
+ * operation and the RcsFeature sets the status of the capability to true using
+ * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}.
+ *
+ * @return An instance of {@link RcsSipOptionsImplBase} that implements SIP options exchange if
+ * it is supported by the device.
+ * @hide
+ */
+ @Override
+ public RcsSipOptionsImplBase getOptionsExchangeImpl() {
+ return null;
+ }
+
+ @Override
+ public void changeEnabledCapabilities(CapabilityChangeRequest request,
+ CapabilityCallbackProxy c) {
+ logd("changeEnabledCapabilities");
+ if (request == null || c == null) {
+ loge("changeEnabledCapabilities :: Invalid argument(s).");
+ return;
+ }
+
+ List<CapabilityPair> capsToEnable = request.getCapabilitiesToEnable();
+ List<CapabilityPair> capsToDisable = request.getCapabilitiesToDisable();
+ if (capsToEnable.isEmpty() && capsToDisable.isEmpty()) {
+ loge("changeEnabledCapabilities :: No CapabilityPair objects to process!");
+ return;
+ }
+
+ for (CapabilityPair cp : capsToEnable) {
+ if (cp.getCapability() == RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE) {
+ // SIP OPTION is not supported
+ callBackError(cp, c);
+ } else if (cp.getCapability() == RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE) {
+ mRcsImsCapabilities.addCapabilities(
+ RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE);
+ enableRcsPresence();
+ }
+ }
+ for (CapabilityPair cp : capsToDisable) {
+ if (cp.getCapability() == RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE) {
+ // SIP OPTION is not supported
+ callBackError(cp, c);
+ } else if (cp.getCapability() == RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE) {
+ mRcsImsCapabilities.removeCapabilities(RcsImsCapabilities
+ .CAPABILITY_TYPE_PRESENCE_UCE);
+ disableRcsPresence();
+ }
+ }
+ }
+
+ private void callBackError(CapabilityPair cp, CapabilityCallbackProxy c) {
+ final Runnable r = new Runnable() {
+ @Override
+ public void run() {
+ c.onChangeCapabilityConfigurationError(cp.getCapability(), cp.getRadioTech(),
+ ImsFeature.CAPABILITY_ERROR_GENERIC);
+ }
+ };
+ if (mFeatureCallbackHandler != null) {
+ mFeatureCallbackHandler.post(r);
+ }
+ }
+
+ private void enableRcsPresence() {
+ RcsManager rcsManager = getRcsManager();
+ if (rcsManager != null) {
+ rcsManager.setPresenceEnabledByFramework(true);
+ }
+ if (rcsManager != null && rcsManager.isRcsServiceAvailable()) {
+ Intent intent = new Intent(RcsManager.ACTION_RCS_SERVICE_AVAILABLE);
+ mContext.sendBroadcast(intent,
+ "com.android.ims.rcs.permission.STATUS_CHANGED");
+ }
+ }
+
+ private void disableRcsPresence() {
+ RcsManager rcsManager = getRcsManager();
+ if (rcsManager != null) {
+ rcsManager.setPresenceEnabledByFramework(false);
+ }
+ Intent intent = new Intent(RcsManager.ACTION_RCS_SERVICE_UNAVAILABLE);
+ mContext.sendBroadcast(intent,
+ "com.android.ims.rcs.permission.STATUS_CHANGED");
+ }
+
+ private RcsManager getRcsManager() {
+ if (isDefaultVoiceSubId()) {
+ return RcsManager.getInstance(mContext, mSubId);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean queryCapabilityConfiguration(
+ @RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+ @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
+ logi("queryCapabilityConfiguration :: capability=" + capability
+ + " radioTech=" + radioTech);
+ return mRcsImsCapabilities != null && mRcsImsCapabilities.isCapable(capability);
+ }
+
+ private final BroadcastReceiver mRcsStateReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ RcsFeatureImpl.this.logi("onReceive(), intent: " + intent + ", context: " + context);
+ String action = intent.getAction();
+ RcsManager rcsManager = getRcsManager();
+ if (RcsManager.ACTION_RCS_SERVICE_AVAILABLE.equals(action)) {
+ // Check if both enableRcsPresence() and StackListener's serviceAvailable() are
+ // executed.
+ if (rcsManager != null && rcsManager.isRcsServiceAvailable()) {
+ notifyCapabilitiesStatusChanged(new RcsImsCapabilities(RcsImsCapabilities
+ .CAPABILITY_TYPE_PRESENCE_UCE));
+ }
+ } else if (RcsManager.ACTION_RCS_SERVICE_UNAVAILABLE.equals(action) ||
+ RcsManager.ACTION_RCS_SERVICE_DIED.equals(action)) {
+ // Triggered from disabledRcsPresence() or StackListener's serviceUnAvailable().
+ if (rcsManager != null) {
+ notifyCapabilitiesStatusChanged(new RcsImsCapabilities(RcsImsCapabilities
+ .CAPABILITY_TYPE_NONE));
+ }
+ }
+ }
+ };
+
+ private final BroadcastReceiver mVoiceSubscriptionReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED.equals(action)) {
+ int newVoiceSubId = SubscriptionManager.getDefaultSubscriptionId();
+ synchronized (mToken) {
+ if (newVoiceSubId != mDefaultVoiceSubId) {
+ mDefaultVoiceSubId = newVoiceSubId;
+ mSubId = getSubId();
+ logd("mVoiceSubscriptionReceiver mSubId:" + mSubId + " "
+ + "mDefaultVoiceSubId:" + mDefaultVoiceSubId);
+ processFeatureChange();
+ }
+ }
+ }
+ }
+ };
+
+ class SubscriptionChangedListener extends SubscriptionManager.OnSubscriptionsChangedListener {
+ @Override
+ public void onSubscriptionsChanged() {
+ int newSubId = getSubId();
+ synchronized (mToken) {
+ if (newSubId != mSubId) {
+ mSubId = newSubId;
+ mDefaultVoiceSubId = SubscriptionManager.getDefaultSubscriptionId();
+ logd("onSubscriptionsChanged mSubId:" + mSubId + " mDefaultVoiceSubId:" +
+ mDefaultVoiceSubId);
+ processFeatureChange();
+ }
+ }
+ }
+ }
+
+ private void processFeatureChange() {
+ if (isDefaultVoiceSubId()) {
+ logd("set STATE_READY");
+ setFeatureState(ImsFeature.STATE_READY);
+ } else {
+ logd("set STATE_UNAVAILABLE");
+ setFeatureState(ImsFeature.STATE_UNAVAILABLE);
+ }
+ }
+
+ private void logd(String s) {
+ Log.d(TAG, "[" + mPhoneId + "][" + mSubId + "] " + s);
+ }
+
+ private void logi(String s) {
+ Log.i(TAG, "[" + mPhoneId + "][" + mSubId + "] " + s);
+ }
+
+ private void loge(String s) {
+ Log.e(TAG, "[" + mPhoneId + "][" + mSubId + "] " + s);
+ }
+}
diff --git a/rcs/rcsservice/src/com/android/service/ims/RcsPresenceExchangeImpl.java b/rcs/rcsservice/src/com/android/service/ims/RcsPresenceExchangeImpl.java
new file mode 100644
index 0000000..3a995f4
--- /dev/null
+++ b/rcs/rcsservice/src/com/android/service/ims/RcsPresenceExchangeImpl.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+package com.android.service.ims;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.Uri;
+import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.stub.RcsPresenceExchangeImplBase;
+import android.util.Log;
+
+import com.android.ims.RcsManager;
+import com.android.ims.RcsPresenceInfo;
+import com.android.service.ims.RcsStackAdaptor;
+import com.android.service.ims.TaskManager;
+
+import java.util.List;
+
+public class RcsPresenceExchangeImpl extends RcsPresenceExchangeImplBase {
+
+ private Context mContext;
+ private static final String TAG = "RcsPresenceExchangeImpl";
+
+ public RcsPresenceExchangeImpl(Context context) {
+ mContext = context;
+ }
+
+
+ /**
+ * The user capabilities of one or multiple contacts have been requested by the framework.
+ * <p>
+ * The implementer must follow up this call with an {@link #onCommandUpdate(int, int)} call to
+ * indicate whether or not this operation succeeded. If this operation succeeds, network
+ * response updates should be sent to the framework using
+ * {@link #onNetworkResponse(int, String, int)}. When the operation is completed,
+ * {@link #onCapabilityRequestResponse(List, int)} should be called with the presence
+ * information for the contacts specified.
+ *
+ * @param uris A {@link List} of the {@link Uri}s that the framework is requesting
+ * the UCE
+ * capabilities for.
+ * @param operationToken The token associated with this operation. Updates to this request using
+ * {@link #onCommandUpdate(int, int)},
+ * {@link #onNetworkResponse(int, String, int)}, and
+ * {@link #onCapabilityRequestResponse(List, int)} must use the same
+ * operation token
+ * in response.
+ */
+ public void requestCapabilities(@NonNull List<Uri> uris, int operationToken) {
+ Log.d(TAG, "requestCapabilities operationToken:" + operationToken);
+ String[] contacts = new String[uris.size()];
+ for (int i = 0; i < uris.size(); i++) {
+ contacts[i] = uris.get(i).toString();
+ }
+ RcsStackAdaptor.getInstance(null).requestCapability(contacts, operationToken);
+ }
+
+ /**
+ * The capabilities of this device have been updated and should be published to the network.
+ * <p>
+ * The implementer must follow up this call with an {@link #onCommandUpdate(int, int)} call to
+ * indicate whether or not this operation succeeded. If this operation succeeds, network
+ * response updates should be sent to the framework using
+ * {@link #onNetworkResponse(int, String, int)}.
+ *
+ * @param capabilities The capabilities for this device.
+ * @param operationToken The token associated with this operation. Any subsequent
+ * {@link #onCommandUpdate(int, int)} or
+ * {@link #onNetworkResponse(int, String, int)}
+ * calls regarding this update must use the same token.
+ */
+ public void updateCapabilities(@NonNull RcsContactUceCapability capabilities,
+ int operationToken) {
+ Log.d(TAG, "updateCapabilities operationToken:" + operationToken);
+ boolean isVolte = capabilities.isCapable(RcsContactUceCapability
+ .CAPABILITY_IP_VOICE_CALL);
+ boolean isVt = capabilities.isCapable(
+ RcsContactUceCapability.CAPABILITY_IP_VIDEO_CALL);
+ int volteState = isVolte ? RcsPresenceInfo.ServiceState.ONLINE
+ : RcsPresenceInfo.ServiceState.OFFLINE;
+ int vtState = isVt ? RcsPresenceInfo.ServiceState.ONLINE
+ : RcsPresenceInfo.ServiceState.OFFLINE;
+ RcsPresenceInfo presenceInfo = new RcsPresenceInfo(capabilities.getContactUri().toString(),
+ RcsPresenceInfo.VolteStatus.VOLTE_UNKNOWN,
+ volteState,
+ null,
+ System.currentTimeMillis(),
+ vtState,
+ null,
+ System.currentTimeMillis()
+ );
+ RcsStackAdaptor.getInstance(null).requestPublication(presenceInfo, null, operationToken);
+ }
+
+}
diff --git a/rcs/rcsservice/src/com/android/service/ims/RcsService.java b/rcs/rcsservice/src/com/android/service/ims/RcsService.java
index 953db2f..5e83d51 100644
--- a/rcs/rcsservice/src/com/android/service/ims/RcsService.java
+++ b/rcs/rcsservice/src/com/android/service/ims/RcsService.java
@@ -80,7 +80,7 @@ public class RcsService extends Service{
logger.debug("RcsService onCreate");
- mRcsStackAdaptor = RcsStackAdaptor.getInstance(this);
+ mRcsStackAdaptor = RcsStackAdaptor.getInstance(null);
mPublication = new PresencePublication(mRcsStackAdaptor, this,
getResources().getStringArray(
diff --git a/rcs/rcsservice/src/com/android/service/ims/RcsServiceApp.java b/rcs/rcsservice/src/com/android/service/ims/RcsServiceApp.java
index c1f683d..c48f1dc 100644
--- a/rcs/rcsservice/src/com/android/service/ims/RcsServiceApp.java
+++ b/rcs/rcsservice/src/com/android/service/ims/RcsServiceApp.java
@@ -39,8 +39,6 @@ public class RcsServiceApp extends Application {
public void onCreate() {
super.onCreate();
logger.debug("in onCreate() of RcsServiceApp");
-
- LauncherUtils.launchRcsService(this);
}
}
diff --git a/rcs/rcsservice/src/com/android/service/ims/RcsStackAdaptor.java b/rcs/rcsservice/src/com/android/service/ims/RcsStackAdaptor.java
index 902f6c7..2f2c2d3 100644
--- a/rcs/rcsservice/src/com/android/service/ims/RcsStackAdaptor.java
+++ b/rcs/rcsservice/src/com/android/service/ims/RcsStackAdaptor.java
@@ -56,6 +56,7 @@ import com.android.ims.ImsConfig;
import com.android.ims.ImsManager;
import com.android.ims.ImsException;
import android.telephony.SubscriptionManager;
+import android.telephony.ims.stub.RcsPresenceExchangeImplBase;
import com.android.ims.IRcsPresenceListener;
import com.android.ims.RcsPresence;
@@ -160,11 +161,11 @@ public class RcsStackAdaptor{
// The singleton.
private static RcsStackAdaptor sInstance = null;
+ private RcsPresenceExchangeImplBase mRcsPresenceExchangeImplBase;
+
// Constructor
private RcsStackAdaptor(Context context) {
mContext = context;
-
- init();
}
public static synchronized RcsStackAdaptor getInstance(Context context) {
@@ -342,7 +343,8 @@ public class RcsStackAdaptor{
return ret;
}
- public int requestPublication(RcsPresenceInfo presenceInfo, IRcsPresenceListener listener) {
+ public int requestPublication(RcsPresenceInfo presenceInfo, IRcsPresenceListener listener,
+ int taskId) {
logger.debug("requestPublication ...");
// Don't use checkStackAndPublish()
@@ -395,7 +397,6 @@ public class RcsStackAdaptor{
return PresencePublication.PUBLISH_GENIRIC_FAILURE;
}
- int taskId = TaskManager.getDefault().addPublishTask(myNumber, listener);
try{
PresCapInfo pMyCapInfo = new PresCapInfo();
// Fill cap info
@@ -614,7 +615,7 @@ public class RcsStackAdaptor{
thread.start();
}
- private void init() {
+ public void init() {
createListeningThread();
logger.debug("after createListeningThread");
@@ -729,6 +730,15 @@ public class RcsStackAdaptor{
clearImsUceService();
}
+ public RcsPresenceExchangeImplBase getRcsPresenceExchangeImplBase() {
+ return mRcsPresenceExchangeImplBase;
+ }
+
+ public void setRcsPresenceExchangeImplBase(
+ RcsPresenceExchangeImplBase rcsPresenceExchangeImplBase) {
+ mRcsPresenceExchangeImplBase = rcsPresenceExchangeImplBase;
+ }
+
protected void finalize() throws Throwable {
super.finalize();
finish();
diff --git a/rcs/rcsservice/src/com/android/service/ims/RcsUtils.java b/rcs/rcsservice/src/com/android/service/ims/RcsUtils.java
index bbfacd2..623fa74 100644
--- a/rcs/rcsservice/src/com/android/service/ims/RcsUtils.java
+++ b/rcs/rcsservice/src/com/android/service/ims/RcsUtils.java
@@ -28,10 +28,19 @@
package com.android.service.ims;
+import static com.android.ims.RcsPresenceInfo.ServiceType.VOLTE_CALL;
+import static com.android.ims.RcsPresenceInfo.ServiceType.VT_CALL;
+
import java.lang.String;
+import java.util.ArrayList;
+
+import android.net.Uri;
import android.telephony.TelephonyManager;
import android.content.Context;
+import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.stub.RcsCapabilityExchange;
+import com.android.ims.RcsPresenceInfo;
import com.android.ims.internal.uce.common.StatusCode;
import com.android.ims.RcsManager.ResultCode;
@@ -90,6 +99,75 @@ public class RcsUtils{
return ResultCode.SUBSCRIBE_GENERIC;
}
+ static public int statusCodeToCommandCode(int sipStatusCode) {
+ if (sipStatusCode == StatusCode.UCE_SUCCESS ||
+ sipStatusCode == StatusCode.UCE_SUCCESS_ASYC_UPDATE) {
+ return RcsCapabilityExchange.COMMAND_CODE_SUCCESS;
+ }
+
+ if (sipStatusCode == StatusCode.UCE_INVALID_PARAM) {
+ return RcsCapabilityExchange.COMMAND_CODE_INVALID_PARAM;
+ }
+
+ if (sipStatusCode == StatusCode.UCE_FETCH_ERROR) {
+ return RcsCapabilityExchange.COMMAND_CODE_FETCH_ERROR;
+ }
+
+ if (sipStatusCode == StatusCode.UCE_REQUEST_TIMEOUT) {
+ return RcsCapabilityExchange.COMMAND_CODE_REQUEST_TIMEOUT;
+ }
+
+ if (sipStatusCode == StatusCode.UCE_INSUFFICIENT_MEMORY) {
+ return RcsCapabilityExchange.COMMAND_CODE_INSUFFICIENT_MEMORY;
+ }
+
+ if (sipStatusCode == StatusCode.UCE_LOST_NET) {
+ return RcsCapabilityExchange.COMMAND_CODE_LOST_NETWORK_CONNECTION;
+ }
+
+ if (sipStatusCode == StatusCode.UCE_NOT_SUPPORTED) {
+ return RcsCapabilityExchange.COMMAND_CODE_NOT_SUPPORTED;
+ }
+
+ if (sipStatusCode == StatusCode.UCE_NOT_FOUND) {
+ return RcsCapabilityExchange.COMMAND_CODE_NOT_FOUND;
+ }
+
+ if (sipStatusCode == StatusCode.UCE_FAILURE ||
+ sipStatusCode == StatusCode.UCE_INVALID_SERVICE_HANDLE ||
+ sipStatusCode == StatusCode.UCE_INVALID_LISTENER_HANDLE) {
+ return RcsCapabilityExchange.COMMAND_CODE_GENERIC_FAILURE;
+ }
+
+ return RcsCapabilityExchange.COMMAND_CODE_GENERIC_FAILURE;
+ }
+
+ static public ArrayList<RcsContactUceCapability> transformToRcsContactUceCapability
+ (ArrayList<RcsPresenceInfo> presenceInfoList) {
+ ArrayList<RcsContactUceCapability> uceCapabilityArrayList = new ArrayList<>(
+ presenceInfoList.size());
+ for (RcsPresenceInfo info : presenceInfoList) {
+ RcsContactUceCapability.Builder builder = new RcsContactUceCapability.Builder(Uri
+ .parse(info.getContactNumber()));
+ if (info.getServiceState(VOLTE_CALL) == RcsPresenceInfo.ServiceState.ONLINE) {
+ builder.add(RcsContactUceCapability.CAPABILITY_IP_VOICE_CALL);
+ }
+ if (info.getServiceState(VT_CALL) == RcsPresenceInfo.ServiceState.ONLINE) {
+ builder.add(RcsContactUceCapability.CAPABILITY_IP_VIDEO_CALL);
+ }
+ uceCapabilityArrayList.add(builder.build());
+ }
+ return uceCapabilityArrayList;
+ }
+
+ static public ArrayList<Uri> transformToUri(String[] contacts) {
+ ArrayList<Uri> list = new ArrayList<>();
+ for(String contact : contacts) {
+ list.add(Uri.parse(contact));
+ }
+ return list;
+ }
+
static public String toContactString(String[] contacts) {
if(contacts == null) {
return null;
diff --git a/rcs/rcsservice/src/com/android/service/ims/TaskManager.java b/rcs/rcsservice/src/com/android/service/ims/TaskManager.java
index 74e11a6..7d11ea3 100644
--- a/rcs/rcsservice/src/com/android/service/ims/TaskManager.java
+++ b/rcs/rcsservice/src/com/android/service/ims/TaskManager.java
@@ -66,6 +66,7 @@ public class TaskManager{
private int mTaskId = 0;
+ public final static int INVALID_ID = -1;
public final static int TASK_TYPE_GET_CAPABILITY = 1;
public final static int TASK_TYPE_GET_AVAILABILITY = 2;
public final static int TASK_TYPE_PUBLISH = 3;
@@ -190,16 +191,16 @@ public class TaskManager{
return null;
}
- public void onTerminated(String contact){ // for single number capability polling
+ public int onTerminated(String contact){ // for single number capability polling
if(contact == null){
- return;
+ return INVALID_ID;
}
synchronized (mSyncObj){
Set<String> keys= mTaskMap.keySet();
if(keys == null){
logger.debug("onTerminated keys is null");
- return;
+ return INVALID_ID;
}
for(String key:keys){
@@ -225,19 +226,21 @@ public class TaskManager{
TASK_MANAGER_ON_TERMINATED,
messageData);
sMsgHandler.sendMessage(notifyMessage);
+ return task.mTaskId;
}
}
}
}
+ return INVALID_ID;
}
- public void onTerminated(int requestId, String reason){
+ public int onTerminated(int requestId, String reason){
logger.debug("onTerminated requestId=" + requestId + " reason=" + reason);
Task task = getTaskByRequestId(requestId);
if(task == null){
logger.debug("onTerminated Can't find request " + requestId);
- return;
+ return INVALID_ID;
}
synchronized (mSyncObj){
@@ -249,8 +252,10 @@ public class TaskManager{
Message notifyMessage = sMsgHandler.obtainMessage(TASK_MANAGER_ON_TERMINATED,
messageData);
sMsgHandler.sendMessage(notifyMessage);
+ return task.mTaskId;
}
}
+ return INVALID_ID;
}
public void onTimeout(int taskId){
diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/PresencePublication.java b/rcs/rcsservice/src/com/android/service/ims/presence/PresencePublication.java
index e7607ee..4e7edb6 100644
--- a/rcs/rcsservice/src/com/android/service/ims/presence/PresencePublication.java
+++ b/rcs/rcsservice/src/com/android/service/ims/presence/PresencePublication.java
@@ -28,53 +28,45 @@
package com.android.service.ims.presence;
-import java.util.List;
-import java.util.Arrays;
-
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import com.android.internal.telephony.Phone;
-import android.provider.Settings;
-import android.os.SystemProperties;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.telephony.TelephonyManager;
-import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.TelephonyIntents;
-import android.telecom.TelecomManager;
import android.content.IntentFilter;
-import android.app.PendingIntent;
-import android.app.AlarmManager;
-import android.os.SystemClock;
-import android.os.Message;
+import android.net.Uri;
import android.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.provider.Settings;
+import android.telecom.TelecomManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.stub.RcsPresenceExchangeImplBase;
-
+import com.android.ims.ImsConfig;
import com.android.ims.ImsManager;
-import com.android.ims.ImsConnectionStateListener;
import com.android.ims.ImsServiceClass;
-import com.android.ims.ImsException;
-import android.telephony.SubscriptionManager;
-import com.android.ims.ImsConfig;
-import com.android.ims.ImsConfig.FeatureConstants;
-import com.android.ims.ImsConfig.FeatureValueConstants;
-
-import com.android.service.ims.RcsSettingUtils;
-import com.android.ims.RcsPresenceInfo;
-import com.android.ims.IRcsPresenceListener;
import com.android.ims.RcsManager.ResultCode;
import com.android.ims.RcsPresence.PublishState;
-
+import com.android.ims.RcsPresenceInfo;
import com.android.ims.internal.Logger;
-import com.android.service.ims.TaskManager;
-import com.android.service.ims.Task;
-
+import com.android.ims.internal.uce.presence.PresCmdStatus;
import com.android.ims.internal.uce.presence.PresPublishTriggerType;
import com.android.ims.internal.uce.presence.PresSipResponse;
-import com.android.ims.internal.uce.common.StatusCode;
-import com.android.ims.internal.uce.presence.PresCmdStatus;
-
+import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.service.ims.RcsPresenceExchangeImpl;
+import com.android.service.ims.RcsSettingUtils;
import com.android.service.ims.RcsStackAdaptor;
+import com.android.service.ims.RcsUtils;
+import com.android.service.ims.Task;
+import com.android.service.ims.TaskManager;
+
+import java.util.Arrays;
public class PresencePublication extends PresenceBase {
private Logger logger = Logger.getLogger(this.getClass().getName());
@@ -932,7 +924,24 @@ public class PresencePublication extends PresenceBase {
mPublishingRequest.setTimestamp(System.currentTimeMillis());
}
- int ret = mRcsStackAdaptor.requestPublication(presenceInfo, null);
+ RcsPresenceExchangeImplBase rcsPresenceExchange = RcsStackAdaptor.getInstance(
+ null).getRcsPresenceExchangeImplBase();
+ int ret = ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
+ if (rcsPresenceExchange != null) {
+ RcsContactUceCapability.Builder builder = new RcsContactUceCapability.Builder(Uri
+ .parse("tel:" + teleMgr.getLine1Number()));
+ int taskId = TaskManager.getDefault().addPublishTask(teleMgr.getLine1Number(), null);
+ if (publishRequest.getVolteCapable()) {
+ builder.add(RcsContactUceCapability.CAPABILITY_IP_VOICE_CALL);
+ }
+ if (publishRequest.getVtCapable()) {
+ builder.add(RcsContactUceCapability.CAPABILITY_IP_VIDEO_CALL);
+ }
+ rcsPresenceExchange.updateCapabilities(builder.build(), taskId);
+ } else {
+ logger.debug("rcsPresenceExchange = null for publish request");
+ }
+
if(ret == ResultCode.ERROR_SERVICE_NOT_AVAILABLE){
mHasCachedTrigger = true;
}else{
@@ -943,6 +952,19 @@ public class PresencePublication extends PresenceBase {
public void handleCmdStatus(PresCmdStatus cmdStatus) {
super.handleCmdStatus(cmdStatus);
+ int commandCode = RcsUtils.statusCodeToCommandCode(cmdStatus.getStatus().getStatusCode());
+ RcsPresenceExchangeImplBase rcsPresenceExchange = RcsStackAdaptor.getInstance(null)
+ .getRcsPresenceExchangeImplBase();
+ logger.debug("publish cmd:" + cmdStatus);
+ if (rcsPresenceExchange != null) {
+ try {
+ rcsPresenceExchange.onCommandUpdate(commandCode, cmdStatus.getUserData());
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ } else {
+ logger.debug("rcsPresenceExchange = null for sip response");
+ }
}
private PendingIntent mRetryAlarmIntent = null;
@@ -1077,6 +1099,24 @@ public class PresencePublication extends PresenceBase {
}
handleCallback(task, getPublishState(), false);
+ notifyFrameworkForPublishResponse(task);
+ }
+
+ private void notifyFrameworkForPublishResponse(Task task) {
+ RcsPresenceExchangeImpl rcsPresenceExchange =
+ (RcsPresenceExchangeImpl) RcsStackAdaptor.getInstance(null)
+ .getRcsPresenceExchangeImplBase();
+ if (rcsPresenceExchange != null) {
+ try {
+ logger.debug("onNetworkResponse task:"+task);
+ rcsPresenceExchange.onNetworkResponse(task.mSipResponseCode, task.mSipReasonPhrase,
+ task.mTaskId);
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ } else {
+ logger.debug("rcsPresenceExchange = null for sip response");
+ }
}
private static boolean isTtyEnabled(int mode) {
diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/PresenceSubscriber.java b/rcs/rcsservice/src/com/android/service/ims/presence/PresenceSubscriber.java
index daa2636..fd2a701 100644
--- a/rcs/rcsservice/src/com/android/service/ims/presence/PresenceSubscriber.java
+++ b/rcs/rcsservice/src/com/android/service/ims/presence/PresenceSubscriber.java
@@ -30,30 +30,19 @@ package com.android.service.ims.presence;
import java.util.List;
import java.util.ArrayList;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.concurrent.Semaphore;
-import android.content.ContentValues;
+import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.stub.RcsCapabilityExchange;
+import android.telephony.ims.stub.RcsPresenceExchangeImplBase;
import android.text.TextUtils;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
-import com.android.internal.telephony.TelephonyIntents;
-import android.os.HandlerThread;
-import android.os.RemoteException;
import android.telephony.TelephonyManager;
-import android.database.Cursor;
import java.lang.String;
-import android.content.Context;
-import android.util.Log;
import com.android.ims.internal.uce.presence.PresSipResponse;
-import com.android.ims.internal.uce.common.StatusCode;
-import com.android.ims.internal.uce.common.StatusCode;
import com.android.ims.internal.uce.presence.PresSubscriptionState;
import com.android.ims.internal.uce.presence.PresCmdStatus;
import com.android.ims.internal.uce.presence.PresResInfo;
@@ -68,6 +57,7 @@ import com.android.ims.RcsPresence.PublishState;
import com.android.ims.internal.Logger;
import com.android.ims.internal.ContactNumberUtils;
+import com.android.service.ims.RcsPresenceExchangeImpl;
import com.android.service.ims.TaskManager;
import com.android.service.ims.Task;
import com.android.service.ims.RcsStackAdaptor;
@@ -160,6 +150,15 @@ public class PresenceSubscriber extends PresenceBase{
for(int i=0; i<formatedContacts.length; i++){
formatedContacts[i] = numberToTelString(formatedNumbers[i]);
}
+
+ RcsPresenceExchangeImplBase rcsPresenceExchange = RcsStackAdaptor.getInstance(
+ null).getRcsPresenceExchangeImplBase();
+ if (rcsPresenceExchange == null) {
+ ret = ResultCode.SUBSCRIBE_GENIRIC_FAILURE;
+ logger.error("rcsPresenceExchange = null");
+ return ret;
+ }
+
// In ms
long timeout = RcsSettingUtils.getCapabPollListSubExp(mContext) * 1000;
timeout += RcsSettingUtils.getSIPT1Timer(mContext);
@@ -176,12 +175,8 @@ public class PresenceSubscriber extends PresenceBase{
listener, timeout);
logger.print("taskId=" + taskId);
- ret = mRcsStackAdaptor.requestCapability(formatedContacts, taskId);
- if(ret < ResultCode.SUCCESS){
- logger.error("requestCapability ret=" + ret + " remove taskId=" + taskId);
- TaskManager.getDefault().removeTask(taskId);
- }
-
+ rcsPresenceExchange.requestCapabilities(RcsUtils.transformToUri(formatedContacts),
+ taskId);
ret = taskId;
return ret;
@@ -444,6 +439,24 @@ public class PresenceSubscriber extends PresenceBase{
}
handleCallback(task, errorCode, false);
+ notifyFrameworkForSubscribeResponse(task);
+ }
+
+ private void notifyFrameworkForSubscribeResponse(Task task) {
+ RcsPresenceExchangeImpl rcsPresenceExchange =
+ (RcsPresenceExchangeImpl) RcsStackAdaptor.getInstance(null)
+ .getRcsPresenceExchangeImplBase();
+ if (rcsPresenceExchange != null) {
+ try {
+ logger.debug("onNetworkResponse taskid=" + task.mTaskId);
+ rcsPresenceExchange.onNetworkResponse(task.mSipResponseCode, task.mSipReasonPhrase,
+ task.mTaskId);
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ } else {
+ logger.debug("rcsPresenceExchange = null for sip response");
+ }
}
private void launchPersistService(Intent intent) {
@@ -481,7 +494,7 @@ public class PresenceSubscriber extends PresenceBase{
rcsPresenceInfoList.add(rcsPresenceInfo);
// For single contact number we got 1 NOTIFY only. So regard it as terminated.
- TaskManager.getDefault().onTerminated(rcsPresenceInfo.getContactNumber());
+ int taskId = TaskManager.getDefault().onTerminated(rcsPresenceInfo.getContactNumber());
PresenceAvailabilityTask availabilityTask = TaskManager.getDefault().
getAvailabilityTaskByContact(rcsPresenceInfo.getContactNumber());
@@ -495,6 +508,7 @@ public class PresenceSubscriber extends PresenceBase{
rcsPresenceInfoList);
intent.putExtra("updateLastTimestamp", true);
launchPersistService(intent);
+ notifyPresence(rcsPresenceInfoList, taskId);
}
public void updatePresences(PresRlmiInfo pRlmiInfo, PresResInfo[] pRcsPresenceInfo) {
@@ -529,8 +543,9 @@ public class PresenceSubscriber extends PresenceBase{
}
}
+ int taskId = TaskManager.INVALID_ID;
if(isTerminated){
- TaskManager.getDefault().onTerminated(pRlmiInfo.getRequestId(),
+ taskId = TaskManager.getDefault().onTerminated(pRlmiInfo.getRequestId(),
pRlmiInfo.getSubscriptionTerminatedReason());
}
@@ -543,6 +558,24 @@ public class PresenceSubscriber extends PresenceBase{
rcsPresenceInfoList);
intent.putExtra("updateLastTimestamp", true);
launchPersistService(intent);
+ notifyPresence(rcsPresenceInfoList, taskId);
+ }
+ }
+
+ private void notifyPresence(ArrayList rcsPresenceInfoList, int taskId) {
+ RcsPresenceExchangeImplBase rcsPresenceExchange = RcsStackAdaptor.getInstance(null)
+ .getRcsPresenceExchangeImplBase();
+ if (rcsPresenceExchange != null) {
+ try {
+ ArrayList<RcsContactUceCapability> list = RcsUtils
+ .transformToRcsContactUceCapability(rcsPresenceInfoList);
+ logger.debug("onCapabilityRequestResponse taskid="+taskId);
+ rcsPresenceExchange.onCapabilityRequestResponse(list, taskId);
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ } else {
+ logger.debug("rcsPresenceExchange = null for sip response");
}
}
@@ -552,7 +585,6 @@ public class PresenceSubscriber extends PresenceBase{
return;
}
-
Task taskTmp = TaskManager.getDefault().getTask(pCmdStatus.getUserData());
int resultCode = RcsUtils.statusCodeToResultCode(pCmdStatus.getStatus().getStatusCode());
logger.print("handleCmdStatus resultCode=" + resultCode);
@@ -565,12 +597,27 @@ public class PresenceSubscriber extends PresenceBase{
// handle error as the same as temporary network error
// set availability to false, keep old capability
- if(resultCode != ResultCode.SUCCESS && task.mContacts != null){
+ if(resultCode != RcsCapabilityExchange.COMMAND_CODE_SUCCESS && task.mContacts !=
+ null){
updateAvailabilityToUnknown(task);
}
}
handleCallback(task, resultCode, true);
+
+ RcsPresenceExchangeImplBase rcsPresenceExchange = RcsStackAdaptor.getInstance(null)
+ .getRcsPresenceExchangeImplBase();
+ if (rcsPresenceExchange != null) {
+ try {
+ logger.print("onCommandUpdate id:"+pCmdStatus.getUserData());
+ int commandCode = RcsUtils.statusCodeToCommandCode(pCmdStatus.getStatus().getStatusCode());
+ rcsPresenceExchange.onCommandUpdate(commandCode, pCmdStatus.getUserData());
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ } else {
+ logger.debug("rcsPresenceExchange = null for sip response");
+ }
}
private void updateAvailabilityToUnknown(Task inTask){
diff --git a/rcs/rcsservice/src/com/android/service/ims/presence/StackListener.java b/rcs/rcsservice/src/com/android/service/ims/presence/StackListener.java
index 9ca82fc..9f15e23 100644
--- a/rcs/rcsservice/src/com/android/service/ims/presence/StackListener.java
+++ b/rcs/rcsservice/src/com/android/service/ims/presence/StackListener.java
@@ -28,19 +28,13 @@
package com.android.service.ims.presence;
-import java.util.ArrayList;
-import java.util.List;
-
-import android.content.ServiceConnection;
-import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.Context;
-import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
-import android.text.TextUtils;
+import android.telephony.ims.stub.RcsPresenceExchangeImplBase;
import android.util.Log;
import android.os.Parcel;
@@ -53,17 +47,11 @@ import com.android.ims.internal.uce.presence.PresRlmiInfo;
import com.android.ims.internal.uce.presence.PresSipResponse;
import com.android.ims.internal.uce.presence.PresTupleInfo;
import com.android.ims.internal.uce.common.StatusCode;
-import com.android.ims.internal.uce.common.StatusCode;
import com.android.ims.RcsManager;
-import com.android.ims.RcsManager.ResultCode;
-import com.android.ims.RcsPresence;
-import com.android.ims.RcsPresenceInfo;
-import com.android.ims.IRcsPresenceListener;
import com.android.ims.internal.Logger;
-import com.android.service.ims.TaskManager;
-import com.android.service.ims.Task;
+import com.android.service.ims.RcsPresenceExchangeImpl;
import com.android.service.ims.RcsStackAdaptor;
public class StackListener extends Handler{
@@ -391,7 +379,18 @@ public class StackListener extends Handler{
publishTrigger.getPublishTrigeerType());
}
logger.debug("ListenerHandler : PublishTriggering");
-
+ RcsPresenceExchangeImplBase rcsPresenceExchange = RcsStackAdaptor.getInstance(null)
+ .getRcsPresenceExchangeImplBase();
+ if (rcsPresenceExchange != null) {
+ try {
+ logger.debug("onNotifyUpdateCapabilites");
+ rcsPresenceExchange.onNotifyUpdateCapabilites();
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ } else {
+ logger.debug("rcsPresenceExchange = null for publishTriggering");
+ }
Message publishTrigerMsg = StackListener.this.obtainMessage(
PRESENCE_IMS_UNSOL_PUBLISH_TRIGGER, publishTrigger);
StackListener.this.sendMessage(publishTrigerMsg);
@@ -532,6 +531,19 @@ public class StackListener extends Handler{
public void unpublishMessageSent() {
logger.debug("unpublishMessageSent()");
+ RcsPresenceExchangeImpl rcsPresenceExchange =
+ (RcsPresenceExchangeImpl) RcsStackAdaptor.getInstance(null)
+ .getRcsPresenceExchangeImplBase();
+ if (rcsPresenceExchange != null) {
+ try {
+ logger.debug("onUnpublish");
+ rcsPresenceExchange.onUnpublish();
+ } catch (Exception e) {
+ logger.error(e.getMessage());
+ }
+ } else {
+ logger.debug("rcsPresenceExchange = null for unpublish sent");
+ }
}
};
}