Add ImsStateCallback
registerImsStateCallback and unregisterImsStateCallback are added to ImsMmTelManager, ImsRcsManager, and SipDelegateManager. Those are used to receive updates about the connection state of the underlying ImsService. Bug: 178016400 Test: atest ImsStateCallbackTest Change-Id: If547ce637725d4f98942b0b554187a0ba91f60de Merged-In: If547ce637725d4f98942b0b554187a0ba91f60de Merged-In: I3ac14cc3bcb28f5f966a1b3c215727784527e475
This commit is contained in:
@@ -43474,8 +43474,10 @@ package android.telephony.ims {
|
||||
method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isVoWiFiSettingEnabled();
|
||||
method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public boolean isVtSettingEnabled();
|
||||
method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
|
||||
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public void registerImsStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsStateCallback) throws android.telephony.ims.ImsException;
|
||||
method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException;
|
||||
method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
|
||||
method public void unregisterImsStateCallback(@NonNull android.telephony.ims.ImsStateCallback);
|
||||
method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void unregisterMmTelCapabilityCallback(@NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback);
|
||||
field public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; // 0x1
|
||||
field public static final int WIFI_MODE_WIFI_ONLY = 0; // 0x0
|
||||
@@ -43492,7 +43494,9 @@ package android.telephony.ims {
|
||||
method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
|
||||
method @NonNull public android.telephony.ims.RcsUceAdapter getUceAdapter();
|
||||
method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
|
||||
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, "android.permission.READ_PRIVILEGED_PHONE_STATE", "android.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE"}) public void registerImsStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsStateCallback) throws android.telephony.ims.ImsException;
|
||||
method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
|
||||
method public void unregisterImsStateCallback(@NonNull android.telephony.ims.ImsStateCallback);
|
||||
field public static final String ACTION_SHOW_CAPABILITY_DISCOVERY_OPT_IN = "android.telephony.ims.action.SHOW_CAPABILITY_DISCOVERY_OPT_IN";
|
||||
}
|
||||
|
||||
@@ -43691,6 +43695,19 @@ package android.telephony.ims {
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsRegistrationAttributes> CREATOR;
|
||||
}
|
||||
|
||||
public abstract class ImsStateCallback {
|
||||
ctor public ImsStateCallback();
|
||||
method public abstract void onAvailable();
|
||||
method public abstract void onError();
|
||||
method public abstract void onUnavailable(int);
|
||||
field public static final int REASON_IMS_SERVICE_DISCONNECTED = 3; // 0x3
|
||||
field public static final int REASON_IMS_SERVICE_NOT_READY = 6; // 0x6
|
||||
field public static final int REASON_NO_IMS_SERVICE_CONFIGURED = 4; // 0x4
|
||||
field public static final int REASON_SUBSCRIPTION_INACTIVE = 5; // 0x5
|
||||
field public static final int REASON_UNKNOWN_PERMANENT_ERROR = 2; // 0x2
|
||||
field public static final int REASON_UNKNOWN_TEMPORARY_ERROR = 1; // 0x1
|
||||
}
|
||||
|
||||
public class RcsUceAdapter {
|
||||
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isUceSettingEnabled() throws android.telephony.ims.ImsException;
|
||||
}
|
||||
|
||||
@@ -13741,7 +13741,9 @@ package android.telephony.ims {
|
||||
method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void createSipDelegate(@NonNull android.telephony.ims.DelegateRequest, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.stub.DelegateConnectionStateCallback, @NonNull android.telephony.ims.stub.DelegateConnectionMessageCallback) throws android.telephony.ims.ImsException;
|
||||
method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void destroySipDelegate(@NonNull android.telephony.ims.SipDelegateConnection, int);
|
||||
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public boolean isSupported() throws android.telephony.ims.ImsException;
|
||||
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void registerImsStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsStateCallback) throws android.telephony.ims.ImsException;
|
||||
method @RequiresPermission(android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void triggerFullNetworkRegistration(@NonNull android.telephony.ims.SipDelegateConnection, @IntRange(from=100, to=699) int, @Nullable String);
|
||||
method public void unregisterImsStateCallback(@NonNull android.telephony.ims.ImsStateCallback);
|
||||
field public static final int DENIED_REASON_INVALID = 4; // 0x4
|
||||
field public static final int DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE = 1; // 0x1
|
||||
field public static final int DENIED_REASON_NOT_ALLOWED = 2; // 0x2
|
||||
|
||||
@@ -119,7 +119,7 @@ public class ImsManager {
|
||||
throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
|
||||
}
|
||||
|
||||
return new ImsRcsManager(mContext, subscriptionId, sRcsCache);
|
||||
return new ImsRcsManager(mContext, subscriptionId, sRcsCache, sTelephonyCache);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,7 +135,7 @@ public class ImsManager {
|
||||
throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
|
||||
}
|
||||
|
||||
return new ImsMmTelManager(subscriptionId, sTelephonyCache);
|
||||
return new ImsMmTelManager(mContext, subscriptionId, sTelephonyCache);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,7 +157,7 @@ public class ImsManager {
|
||||
throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
|
||||
}
|
||||
|
||||
return new SipDelegateManager(mContext, subscriptionId, sRcsCache);
|
||||
return new SipDelegateManager(mContext, subscriptionId, sRcsCache, sTelephonyCache);
|
||||
}
|
||||
|
||||
private static IImsRcsController getIImsRcsControllerInterface() {
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.annotation.RequiresPermission;
|
||||
import android.annotation.SuppressAutoDoc;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.SystemApi;
|
||||
import android.content.Context;
|
||||
import android.os.Binder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceSpecificException;
|
||||
@@ -45,6 +46,7 @@ import com.android.internal.telephony.ITelephony;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -214,6 +216,7 @@ public class ImsMmTelManager implements RegistrationManager {
|
||||
}
|
||||
}
|
||||
|
||||
private final Context mContext;
|
||||
private final int mSubId;
|
||||
private final BinderCacheManager<ITelephony> mBinderCache;
|
||||
|
||||
@@ -255,6 +258,16 @@ public class ImsMmTelManager implements RegistrationManager {
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public ImsMmTelManager(int subId, BinderCacheManager<ITelephony> binderCache) {
|
||||
this(null, subId, binderCache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only visible for testing, use {@link ImsManager#getImsMmTelManager(int)} instead.
|
||||
* @hide
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public ImsMmTelManager(Context context, int subId, BinderCacheManager<ITelephony> binderCache) {
|
||||
mContext = context;
|
||||
mSubId = subId;
|
||||
mBinderCache = binderCache;
|
||||
}
|
||||
@@ -1482,6 +1495,74 @@ public class ImsMmTelManager implements RegistrationManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new callback, which is used to notify the registrant of changes to
|
||||
* the state of the underlying IMS service that is attached to telephony to
|
||||
* implement IMS functionality. If the manager is created for
|
||||
* the {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID},
|
||||
* this throws an {@link ImsException}.
|
||||
*
|
||||
* <p>Requires Permission:
|
||||
* {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE READ_PRECISE_PHONE_STATE}
|
||||
* or that the calling app has carrier privileges
|
||||
* (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}).
|
||||
*
|
||||
* @param executor the Executor that will be used to call the {@link ImsStateCallback}.
|
||||
* @param callback The callback instance being registered.
|
||||
* @throws ImsException in the case that the callback can not be registered.
|
||||
* See {@link ImsException#getCode} for more information on when this is called.
|
||||
*/
|
||||
@RequiresPermission(anyOf = {Manifest.permission.READ_PRECISE_PHONE_STATE,
|
||||
Manifest.permission.READ_PRIVILEGED_PHONE_STATE})
|
||||
public void registerImsStateCallback(@NonNull Executor executor,
|
||||
@NonNull ImsStateCallback callback) throws ImsException {
|
||||
Objects.requireNonNull(callback, "Must include a non-null ImsStateCallback.");
|
||||
Objects.requireNonNull(executor, "Must include a non-null Executor.");
|
||||
|
||||
callback.init(executor);
|
||||
ITelephony telephony = mBinderCache.listenOnBinder(callback, callback::binderDied);
|
||||
if (telephony == null) {
|
||||
throw new ImsException("Telephony server is down",
|
||||
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
try {
|
||||
telephony.registerImsStateCallback(
|
||||
mSubId, ImsFeature.FEATURE_MMTEL,
|
||||
callback.getCallbackBinder(), getOpPackageName());
|
||||
} catch (ServiceSpecificException e) {
|
||||
throw new ImsException(e.getMessage(), e.errorCode);
|
||||
} catch (RemoteException | IllegalStateException e) {
|
||||
throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a previously registered callback.
|
||||
*
|
||||
* @param callback The callback instance to be unregistered.
|
||||
*/
|
||||
public void unregisterImsStateCallback(@NonNull ImsStateCallback callback) {
|
||||
Objects.requireNonNull(callback, "Must include a non-null ImsStateCallback.");
|
||||
|
||||
ITelephony telephony = mBinderCache.removeRunnable(callback);
|
||||
try {
|
||||
if (telephony != null) {
|
||||
telephony.unregisterImsStateCallback(callback.getCallbackBinder());
|
||||
}
|
||||
} catch (RemoteException ignore) {
|
||||
// ignore it
|
||||
}
|
||||
}
|
||||
|
||||
private String getOpPackageName() {
|
||||
if (mContext != null) {
|
||||
return mContext.getOpPackageName();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private ITelephony getITelephony() {
|
||||
return mBinderCache.getBinder();
|
||||
}
|
||||
|
||||
@@ -39,9 +39,11 @@ import android.telephony.ims.stub.ImsRegistrationImplBase;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.telephony.IIntegerConsumer;
|
||||
import com.android.internal.telephony.ITelephony;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -159,6 +161,7 @@ public class ImsRcsManager {
|
||||
private final int mSubId;
|
||||
private final Context mContext;
|
||||
private final BinderCacheManager<IImsRcsController> mBinderCache;
|
||||
private final BinderCacheManager<ITelephony> mTelephonyBinderCache;
|
||||
private final Map<OnAvailabilityChangedListener, AvailabilityCallbackAdapter>
|
||||
mAvailabilityChangedCallbacks;
|
||||
|
||||
@@ -167,11 +170,13 @@ public class ImsRcsManager {
|
||||
* @hide
|
||||
*/
|
||||
public ImsRcsManager(Context context, int subId,
|
||||
BinderCacheManager<IImsRcsController> binderCache) {
|
||||
BinderCacheManager<IImsRcsController> binderCache,
|
||||
BinderCacheManager<ITelephony> telephonyBinderCache) {
|
||||
mSubId = subId;
|
||||
mContext = context;
|
||||
mBinderCache = binderCache;
|
||||
mAvailabilityChangedCallbacks = new HashMap<>();
|
||||
mTelephonyBinderCache = telephonyBinderCache;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -533,6 +538,67 @@ public class ImsRcsManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new callback, which is used to notify the registrant of changes to
|
||||
* the state of the underlying IMS service that is attached to telephony to
|
||||
* implement IMS functionality. If the manager is created for
|
||||
* the {@link android.telephony.SubscriptionManager#DEFAULT_SUBSCRIPTION_ID},
|
||||
* this throws an {@link ImsException}.
|
||||
*
|
||||
* <p>Requires Permission:
|
||||
* {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE READ_PRECISE_PHONE_STATE}
|
||||
* or that the calling app has carrier privileges
|
||||
* (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}).
|
||||
*
|
||||
* @param executor the Executor that will be used to call the {@link ImsStateCallback}.
|
||||
* @param callback The callback instance being registered.
|
||||
* @throws ImsException in the case that the callback can not be registered.
|
||||
* See {@link ImsException#getCode} for more information on when this is called.
|
||||
*/
|
||||
@RequiresPermission(anyOf = {Manifest.permission.READ_PRECISE_PHONE_STATE,
|
||||
Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
|
||||
Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE})
|
||||
public void registerImsStateCallback(@NonNull Executor executor,
|
||||
@NonNull ImsStateCallback callback) throws ImsException {
|
||||
Objects.requireNonNull(callback, "Must include a non-null ImsStateCallback.");
|
||||
Objects.requireNonNull(executor, "Must include a non-null Executor.");
|
||||
|
||||
callback.init(executor);
|
||||
ITelephony telephony = mTelephonyBinderCache.listenOnBinder(callback, callback::binderDied);
|
||||
if (telephony == null) {
|
||||
throw new ImsException("Telephony server is down",
|
||||
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
try {
|
||||
telephony.registerImsStateCallback(
|
||||
mSubId, ImsFeature.FEATURE_RCS,
|
||||
callback.getCallbackBinder(), mContext.getOpPackageName());
|
||||
} catch (ServiceSpecificException e) {
|
||||
throw new ImsException(e.getMessage(), e.errorCode);
|
||||
} catch (RemoteException | IllegalStateException e) {
|
||||
throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a previously registered callback.
|
||||
*
|
||||
* @param callback The callback instance to be unregistered.
|
||||
*/
|
||||
public void unregisterImsStateCallback(@NonNull ImsStateCallback callback) {
|
||||
Objects.requireNonNull(callback, "Must include a non-null ImsStateCallback.");
|
||||
|
||||
ITelephony telephony = mTelephonyBinderCache.removeRunnable(callback);
|
||||
try {
|
||||
if (telephony != null) {
|
||||
telephony.unregisterImsStateCallback(callback.getCallbackBinder());
|
||||
}
|
||||
} catch (RemoteException ignore) {
|
||||
// ignore it
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the {@link OnAvailabilityChangedListener} to collection for tracking.
|
||||
* @param executor The executor that will be used when the publish state is changed and the
|
||||
|
||||
184
telephony/java/android/telephony/ims/ImsStateCallback.java
Normal file
184
telephony/java/android/telephony/ims/ImsStateCallback.java
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.ims;
|
||||
|
||||
import android.annotation.CallbackExecutor;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.os.Binder;
|
||||
|
||||
import com.android.internal.telephony.IImsStateCallback;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* A callback class used for monitoring changes in IMS service connection states
|
||||
* for a specific subscription.
|
||||
* <p>
|
||||
* @see ImsMmTelManager#registerImsStateCallback(Executor, ImsStateCallback)
|
||||
* @see ImsRcsManager#registerImsStateCallback(Executor, ImsStateCallback)
|
||||
*/
|
||||
public abstract class ImsStateCallback {
|
||||
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(prefix = "REASON_", value = {
|
||||
REASON_UNKNOWN_TEMPORARY_ERROR,
|
||||
REASON_UNKNOWN_PERMANENT_ERROR,
|
||||
REASON_IMS_SERVICE_DISCONNECTED,
|
||||
REASON_NO_IMS_SERVICE_CONFIGURED,
|
||||
REASON_SUBSCRIPTION_INACTIVE,
|
||||
REASON_IMS_SERVICE_NOT_READY
|
||||
})
|
||||
public @interface DisconnectedReason {}
|
||||
|
||||
/**
|
||||
* The underlying IMS service is temporarily unavailable for the
|
||||
* associated subscription.
|
||||
* {@link #onAvailable} will be called when the IMS service becomes
|
||||
* available again.
|
||||
*/
|
||||
public static final int REASON_UNKNOWN_TEMPORARY_ERROR = 1;
|
||||
|
||||
/**
|
||||
* The underlying IMS service is permanently unavailable for the
|
||||
* associated subscription and there will be no Manager available for
|
||||
* this subscription.
|
||||
*/
|
||||
public static final int REASON_UNKNOWN_PERMANENT_ERROR = 2;
|
||||
|
||||
/**
|
||||
* The underlying IMS service has died, is reconfiguring, or has never
|
||||
* come up yet and as a result is currently unavailable.
|
||||
* {@link #onAvailable} will be called when the IMS service becomes
|
||||
* available. All callbacks should be unregistered now and registered again
|
||||
* if the IMS service moves back to available.
|
||||
*/
|
||||
public static final int REASON_IMS_SERVICE_DISCONNECTED = 3;
|
||||
|
||||
/**
|
||||
* There is no IMS service configured for the subscription ID specified.
|
||||
* This is a permanent error and there will be no Manager available for
|
||||
* this subscription.
|
||||
*/
|
||||
public static final int REASON_NO_IMS_SERVICE_CONFIGURED = 4;
|
||||
|
||||
/**
|
||||
* The subscription associated with this Manager has moved to an inactive
|
||||
* state (e.g. SIM removed) and the IMS service has torn down the resources
|
||||
* related to this subscription. This has caused this callback
|
||||
* to be deregistered. The callback must be re-registered when this subscription
|
||||
* becomes active in order to continue listening to the IMS service state.
|
||||
*/
|
||||
public static final int REASON_SUBSCRIPTION_INACTIVE = 5;
|
||||
|
||||
/**
|
||||
* The IMS service is connected, but in a NOT_READY state. Once the
|
||||
* service moves to ready, {@link #onAvailable} will be called.
|
||||
*/
|
||||
public static final int REASON_IMS_SERVICE_NOT_READY = 6;
|
||||
|
||||
private IImsStateCallbackStub mCallback;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public void init(@NonNull @CallbackExecutor Executor executor) {
|
||||
if (executor == null) {
|
||||
throw new IllegalArgumentException("ImsStateCallback Executor must be non-null");
|
||||
}
|
||||
mCallback = new IImsStateCallbackStub(this, executor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Using a static class and weak reference here to avoid memory leak caused by the
|
||||
* IImsStateCallback.Stub callback retaining references to the outside ImsStateCallback.
|
||||
*/
|
||||
private static class IImsStateCallbackStub extends IImsStateCallback.Stub {
|
||||
private WeakReference<ImsStateCallback> mImsStateCallbackWeakRef;
|
||||
private Executor mExecutor;
|
||||
|
||||
IImsStateCallbackStub(ImsStateCallback imsStateCallback, Executor executor) {
|
||||
mImsStateCallbackWeakRef = new WeakReference<ImsStateCallback>(imsStateCallback);
|
||||
mExecutor = executor;
|
||||
}
|
||||
|
||||
Executor getExecutor() {
|
||||
return mExecutor;
|
||||
}
|
||||
|
||||
public void onAvailable() {
|
||||
ImsStateCallback callback = mImsStateCallbackWeakRef.get();
|
||||
if (callback == null) return;
|
||||
|
||||
Binder.withCleanCallingIdentity(
|
||||
() -> mExecutor.execute(() -> callback.onAvailable()));
|
||||
}
|
||||
|
||||
public void onUnavailable(int reason) {
|
||||
ImsStateCallback callback = mImsStateCallbackWeakRef.get();
|
||||
if (callback == null) return;
|
||||
|
||||
Binder.withCleanCallingIdentity(
|
||||
() -> mExecutor.execute(() -> callback.onUnavailable(reason)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The IMS service has disconnected or is reporting NOT_READY and is no longer
|
||||
* available to users. The user should clean up all related state and
|
||||
* unregister callbacks. If it is a temporary error, {@link #onAvailable} will
|
||||
* be called when the IMS service becomes available again.
|
||||
*
|
||||
* @param reason the specified reason
|
||||
*/
|
||||
public abstract void onUnavailable(@DisconnectedReason int reason);
|
||||
|
||||
/**
|
||||
* The IMS service is connected and is ready for communication over the
|
||||
* provided Manager.
|
||||
*/
|
||||
public abstract void onAvailable();
|
||||
|
||||
/**
|
||||
* An unexpected error has occurred and the Telephony process has crashed. This
|
||||
* has caused this callback to be deregistered. The callback must be
|
||||
* re-registered in order to continue listening to the IMS service state.
|
||||
*/
|
||||
public abstract void onError();
|
||||
|
||||
/**
|
||||
* The callback to notify the death of telephony process
|
||||
* @hide
|
||||
*/
|
||||
public final void binderDied() {
|
||||
if (mCallback != null) {
|
||||
mCallback.getExecutor().execute(() -> onError());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the callback binder
|
||||
* @hide
|
||||
*/
|
||||
public IImsStateCallbackStub getCallbackBinder() {
|
||||
return mCallback;
|
||||
}
|
||||
}
|
||||
@@ -28,15 +28,16 @@ import android.content.pm.PackageManager;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceSpecificException;
|
||||
import android.telephony.BinderCacheManager;
|
||||
import android.telephony.CarrierConfigManager;
|
||||
import android.telephony.ims.aidl.IImsRcsController;
|
||||
import android.telephony.ims.aidl.SipDelegateConnectionAidlWrapper;
|
||||
import android.telephony.ims.feature.ImsFeature;
|
||||
import android.telephony.ims.stub.DelegateConnectionMessageCallback;
|
||||
import android.telephony.ims.stub.DelegateConnectionStateCallback;
|
||||
import android.telephony.ims.stub.SipDelegate;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.telephony.ITelephony;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
@@ -282,6 +283,7 @@ public class SipDelegateManager {
|
||||
private final Context mContext;
|
||||
private final int mSubId;
|
||||
private final BinderCacheManager<IImsRcsController> mBinderCache;
|
||||
private final BinderCacheManager<ITelephony> mTelephonyBinderCache;
|
||||
|
||||
/**
|
||||
* Only visible for testing. To instantiate an instance of this class, please use
|
||||
@@ -290,10 +292,12 @@ public class SipDelegateManager {
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public SipDelegateManager(Context context, int subId,
|
||||
BinderCacheManager<IImsRcsController> binderCache) {
|
||||
BinderCacheManager<IImsRcsController> binderCache,
|
||||
BinderCacheManager<ITelephony> telephonyBinderCache) {
|
||||
mContext = context;
|
||||
mSubId = subId;
|
||||
mBinderCache = binderCache;
|
||||
mTelephonyBinderCache = telephonyBinderCache;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -446,4 +450,65 @@ public class SipDelegateManager {
|
||||
+ " into this method");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new callback, which is used to notify the registrant of changes to
|
||||
* the state of the underlying IMS service that is attached to telephony to
|
||||
* implement IMS functionality. If the manager is created for
|
||||
* the {@link android.telephony.SubscriptionManager#DEFAULT_SUBSCRIPTION_ID},
|
||||
* this throws an {@link ImsException}.
|
||||
*
|
||||
* <p>Requires Permission:
|
||||
* {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE READ_PRECISE_PHONE_STATE}
|
||||
* or that the calling app has carrier privileges
|
||||
* (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}).
|
||||
*
|
||||
* @param executor the Executor that will be used to call the {@link ImsStateCallback}.
|
||||
* @param callback The callback instance being registered.
|
||||
* @throws ImsException in the case that the callback can not be registered.
|
||||
* See {@link ImsException#getCode} for more information on when this is called.
|
||||
*/
|
||||
@RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
|
||||
Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION})
|
||||
public void registerImsStateCallback(@NonNull Executor executor,
|
||||
@NonNull ImsStateCallback callback) throws ImsException {
|
||||
Objects.requireNonNull(callback, "Must include a non-null ImsStateCallback.");
|
||||
Objects.requireNonNull(executor, "Must include a non-null Executor.");
|
||||
|
||||
callback.init(executor);
|
||||
ITelephony telephony = mTelephonyBinderCache.listenOnBinder(callback, callback::binderDied);
|
||||
if (telephony == null) {
|
||||
throw new ImsException("Telephony server is down",
|
||||
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
|
||||
}
|
||||
|
||||
try {
|
||||
telephony.registerImsStateCallback(
|
||||
mSubId, ImsFeature.FEATURE_RCS,
|
||||
callback.getCallbackBinder(), mContext.getOpPackageName());
|
||||
} catch (ServiceSpecificException e) {
|
||||
throw new ImsException(e.getMessage(), e.errorCode);
|
||||
} catch (RemoteException | IllegalStateException e) {
|
||||
throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters a previously registered callback.
|
||||
*
|
||||
* @param callback The callback instance to be unregistered.
|
||||
*/
|
||||
public void unregisterImsStateCallback(@NonNull ImsStateCallback callback) {
|
||||
Objects.requireNonNull(callback, "Must include a non-null ImsStateCallback.");
|
||||
|
||||
ITelephony telephony = mTelephonyBinderCache.removeRunnable(callback);
|
||||
|
||||
try {
|
||||
if (telephony != null) {
|
||||
telephony.unregisterImsStateCallback(callback.getCallbackBinder());
|
||||
}
|
||||
} catch (RemoteException ignore) {
|
||||
// ignore it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.internal.telephony;
|
||||
|
||||
oneway interface IImsStateCallback {
|
||||
void onUnavailable(int reason);
|
||||
void onAvailable();
|
||||
}
|
||||
@@ -67,6 +67,7 @@ import com.android.ims.internal.IImsServiceFeatureCallback;
|
||||
import com.android.internal.telephony.CellNetworkScanResult;
|
||||
import com.android.internal.telephony.IBooleanConsumer;
|
||||
import com.android.internal.telephony.ICallForwardingInfoCallback;
|
||||
import com.android.internal.telephony.IImsStateCallback;
|
||||
import com.android.internal.telephony.IIntegerConsumer;
|
||||
import com.android.internal.telephony.INumberVerificationCallback;
|
||||
import com.android.internal.telephony.OperatorInfo;
|
||||
@@ -2497,4 +2498,15 @@ interface ITelephony {
|
||||
* NSSAIs (configured, allowed and rejected).
|
||||
*/
|
||||
void getSlicingConfig(in ResultReceiver callback);
|
||||
|
||||
/**
|
||||
* Register an IMS connection state callback
|
||||
*/
|
||||
void registerImsStateCallback(int subId, int feature, in IImsStateCallback cb,
|
||||
in String callingPackage);
|
||||
|
||||
/**
|
||||
* Unregister an IMS connection state callback
|
||||
*/
|
||||
void unregisterImsStateCallback(in IImsStateCallback cb);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user