diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java index 406f01e82c353..f1f683c70735e 100644 --- a/telephony/java/android/telephony/ims/ImsService.java +++ b/telephony/java/android/telephony/ims/ImsService.java @@ -18,6 +18,7 @@ package android.telephony.ims; import android.app.PendingIntent; import android.content.Intent; +import android.content.pm.PackageManager; import android.os.IBinder; import android.os.Message; import android.os.RemoteException; @@ -43,6 +44,7 @@ import com.android.internal.annotations.VisibleForTesting; import static android.Manifest.permission.MODIFY_PHONE_STATE; import static android.Manifest.permission.READ_PHONE_STATE; +import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE; /** * Main ImsService implementation, which binds via the Telephony ImsResolver. Services that extend @@ -137,7 +139,7 @@ public abstract class ImsService extends ImsServiceBase { @Override public boolean isConnected(int slotId, int featureType, int callSessionType, int callType) throws RemoteException { - enforceCallingOrSelfPermission(READ_PHONE_STATE, "isConnected"); + enforceReadPhoneStatePermission("isConnected"); synchronized (mFeatures) { MMTelFeature feature = resolveMMTelFeature(slotId, featureType); if (feature != null) { @@ -149,7 +151,7 @@ public abstract class ImsService extends ImsServiceBase { @Override public boolean isOpened(int slotId, int featureType) throws RemoteException { - enforceCallingOrSelfPermission(READ_PHONE_STATE, "isOpened"); + enforceReadPhoneStatePermission("isOpened"); synchronized (mFeatures) { MMTelFeature feature = resolveMMTelFeature(slotId, featureType); if (feature != null) { @@ -161,7 +163,7 @@ public abstract class ImsService extends ImsServiceBase { @Override public int getFeatureStatus(int slotId, int featureType) throws RemoteException { - enforceCallingOrSelfPermission(READ_PHONE_STATE, "getFeatureStatus"); + enforceReadPhoneStatePermission("getFeatureStatus"); int status = ImsFeature.STATE_NOT_AVAILABLE; synchronized (mFeatures) { SparseArray featureMap = mFeatures.get(slotId); @@ -178,7 +180,7 @@ public abstract class ImsService extends ImsServiceBase { @Override public void addRegistrationListener(int slotId, int featureType, IImsRegistrationListener listener) throws RemoteException { - enforceCallingOrSelfPermission(READ_PHONE_STATE, "addRegistrationListener"); + enforceReadPhoneStatePermission("addRegistrationListener"); synchronized (mFeatures) { MMTelFeature feature = resolveMMTelFeature(slotId, featureType); if (feature != null) { @@ -190,7 +192,7 @@ public abstract class ImsService extends ImsServiceBase { @Override public void removeRegistrationListener(int slotId, int featureType, IImsRegistrationListener listener) throws RemoteException { - enforceCallingOrSelfPermission(READ_PHONE_STATE, "removeRegistrationListener"); + enforceReadPhoneStatePermission("removeRegistrationListener"); synchronized (mFeatures) { MMTelFeature feature = resolveMMTelFeature(slotId, featureType); if (feature != null) { @@ -351,6 +353,8 @@ public abstract class ImsService extends ImsServiceBase { } ImsFeature f = makeImsFeature(slotId, featureType); if (f != null) { + f.setContext(this); + f.setSlotId(slotId); f.setImsFeatureStatusCallback(c); featureMap.put(featureType, f); } @@ -433,6 +437,17 @@ public abstract class ImsService extends ImsServiceBase { return null; } + /** + * Check for both READ_PHONE_STATE and READ_PRIVILEGED_PHONE_STATE. READ_PHONE_STATE is a + * public permission and READ_PRIVILEGED_PHONE_STATE is only granted to system apps. + */ + private void enforceReadPhoneStatePermission(String fn) { + if (checkCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE) + != PackageManager.PERMISSION_GRANTED) { + enforceCallingOrSelfPermission(READ_PHONE_STATE, fn); + } + } + /** * @return An implementation of MMTelFeature that will be used by the system for MMTel * functionality. Must be able to handle emergency calls at any time as well. diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java index 8d7d260104e28..988dd588ecad7 100644 --- a/telephony/java/android/telephony/ims/feature/ImsFeature.java +++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java @@ -17,7 +17,10 @@ package android.telephony.ims.feature; import android.annotation.IntDef; +import android.content.Context; +import android.content.Intent; import android.os.RemoteException; +import android.telephony.SubscriptionManager; import android.util.Log; import com.android.ims.internal.IImsFeatureStatusCallback; @@ -35,6 +38,32 @@ public abstract class ImsFeature { private static final String LOG_TAG = "ImsFeature"; + /** + * Action to broadcast when ImsService is up. + * Internal use only. + * Only defined here separately compatibility purposes with the old ImsService. + * @hide + */ + public static final String ACTION_IMS_SERVICE_UP = + "com.android.ims.IMS_SERVICE_UP"; + + /** + * Action to broadcast when ImsService is down. + * Internal use only. + * Only defined here separately for compatibility purposes with the old ImsService. + * @hide + */ + public static final String ACTION_IMS_SERVICE_DOWN = + "com.android.ims.IMS_SERVICE_DOWN"; + + /** + * Part of the ACTION_IMS_SERVICE_UP or _DOWN intents. + * A long value; the phone ID corresponding to the IMS service coming up or down. + * Only defined here separately for compatibility purposes with the old ImsService. + * @hide + */ + public static final String EXTRA_PHONE_ID = "android:phone_id"; + // Invalid feature value public static final int INVALID = -1; // ImsFeatures that are defined in the Manifests. Ensure that these values match the previously @@ -61,11 +90,21 @@ public abstract class ImsFeature { private List mRemovedListeners = new ArrayList<>(); private IImsFeatureStatusCallback mStatusCallback; private @ImsState int mState = STATE_NOT_AVAILABLE; + private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX; + private Context mContext; public interface INotifyFeatureRemoved { void onFeatureRemoved(int slotId); } + public void setContext(Context context) { + mContext = context; + } + + public void setSlotId(int slotId) { + mSlotId = slotId; + } + public void addFeatureRemovedListener(INotifyFeatureRemoved listener) { synchronized (mRemovedListeners) { mRemovedListeners.add(listener); @@ -118,6 +157,30 @@ public abstract class ImsFeature { Log.w(LOG_TAG, "Couldn't notify feature state: " + e.getMessage()); } } + sendImsServiceIntent(state); + } + + /** + * Provide backwards compatibility using deprecated service UP/DOWN intents. + */ + private void sendImsServiceIntent(@ImsState int state) { + if(mContext == null || mSlotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) { + return; + } + Intent intent; + switch (state) { + case ImsFeature.STATE_NOT_AVAILABLE: + case ImsFeature.STATE_INITIALIZING: + intent = new Intent(ACTION_IMS_SERVICE_DOWN); + break; + case ImsFeature.STATE_READY: + intent = new Intent(ACTION_IMS_SERVICE_UP); + break; + default: + intent = new Intent(ACTION_IMS_SERVICE_DOWN); + } + intent.putExtra(EXTRA_PHONE_ID, mSlotId); + mContext.sendBroadcast(intent); } /**