Do not enforce PHONE_STATE_PERMISSION to register listener

PHONE_STATE_PERMISSION should not be required to register to the following
event types:
- PhoneStateListener.LISTEN_CALL_STATE
- PhoneStateListener.LISTEN_DATA_ACTIVITY
- PhoneStateListener.LISTEN_DATA_CONNECTION_STATE

In case of LISTEN_CALL_STATE, an empty string should be passed instead of
incomingNumber, when caller has no PHONE_STATE_PERMISSION.

Bug: 21588537
Change-Id: I5b6d0308924f7e4cd13a983b8e0c9b3a5bbb119b
This commit is contained in:
Fyodor Kupolov
2015-06-03 16:29:01 -07:00
parent 66f6cd63b7
commit 309b2f63f3
2 changed files with 56 additions and 30 deletions

View File

@@ -92,7 +92,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
IPhoneStateListener callback;
IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback;
int callerUid;
int callerUserId;
int events;
@@ -100,6 +100,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
int phoneId = SubscriptionManager.INVALID_PHONE_INDEX;
boolean canReadPhoneState;
boolean matchPhoneStateListenerEvent(int events) {
return (callback != null) && ((events & this.events) != 0);
}
@@ -114,8 +116,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
+ " callback=" + callback
+ " onSubscriptionsChangedListenererCallback="
+ onSubscriptionsChangedListenerCallback
+ " callerUid=" + callerUid + " subId=" + subId + " phoneId=" + phoneId
+ " events=" + Integer.toHexString(events) + "}";
+ " callerUserId=" + callerUserId + " subId=" + subId + " phoneId=" + phoneId
+ " events=" + Integer.toHexString(events)
+ " canReadPhoneState=" + canReadPhoneState + "}";
}
}
@@ -190,13 +193,15 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
private PreciseDataConnectionState mPreciseDataConnectionState =
new PreciseDataConnectionState();
static final int PHONE_STATE_PERMISSION_MASK =
static final int ENFORCE_PHONE_STATE_PERMISSION_MASK =
PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR |
PhoneStateListener.LISTEN_VOLTE_STATE;
static final int CHECK_PHONE_STATE_PERMISSION_MASK =
PhoneStateListener.LISTEN_CALL_STATE |
PhoneStateListener.LISTEN_DATA_ACTIVITY |
PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR |
PhoneStateListener.LISTEN_VOLTE_STATE;;
PhoneStateListener.LISTEN_DATA_CONNECTION_STATE;
static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
PhoneStateListener.LISTEN_PRECISE_CALL_STATE |
@@ -348,11 +353,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
@Override
public void addOnSubscriptionsChangedListener(String callingPackage,
IOnSubscriptionsChangedListener callback) {
int callerUid = UserHandle.getCallingUserId();
int myUid = UserHandle.myUserId();
int callerUserId = UserHandle.getCallingUserId();
if (VDBG) {
log("listen oscl: E pkg=" + callingPackage + " myUid=" + myUid
+ " callerUid=" + callerUid + " callback=" + callback
log("listen oscl: E pkg=" + callingPackage + " myUserId=" + UserHandle.myUserId()
+ " callerUserId=" + callerUserId + " callback=" + callback
+ " callback.asBinder=" + callback.asBinder());
}
@@ -364,7 +368,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
return;
}
Record r = null;
final Record r;
synchronized (mRecords) {
// register
@@ -385,8 +389,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
r.onSubscriptionsChangedListenerCallback = callback;
r.callingPackage = callingPackage;
r.callerUid = callerUid;
r.callerUserId = callerUserId;
r.events = 0;
r.canReadPhoneState = true; // permission has been enforced above
if (DBG) {
log("listen oscl: Register r=" + r);
}
@@ -454,19 +459,18 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
private void listen(String callingPackage, IPhoneStateListener callback, int events,
boolean notifyNow, int subId) {
int callerUid = UserHandle.getCallingUserId();
int myUid = UserHandle.myUserId();
int callerUserId = UserHandle.getCallingUserId();
if (VDBG) {
log("listen: E pkg=" + callingPackage + " events=0x" + Integer.toHexString(events)
+ " notifyNow=" + notifyNow + " subId=" + subId + " myUid=" + myUid
+ " callerUid=" + callerUid);
+ " notifyNow=" + notifyNow + " subId=" + subId + " myUserId="
+ UserHandle.myUserId() + " callerUserId=" + callerUserId);
}
if (events != PhoneStateListener.LISTEN_NONE) {
/* Checks permission and throws Security exception */
checkListenerPermission(events);
if ((events & PHONE_STATE_PERMISSION_MASK) != 0) {
if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) {
if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
callingPackage) != AppOpsManager.MODE_ALLOWED) {
return;
@@ -475,7 +479,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
synchronized (mRecords) {
// register
Record r = null;
Record r;
find_and_add: {
IBinder b = callback.asBinder();
final int N = mRecords.size();
@@ -493,7 +497,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
r.callback = callback;
r.callingPackage = callingPackage;
r.callerUid = callerUid;
r.callerUserId = callerUserId;
boolean isPhoneStateEvent = (events & (CHECK_PHONE_STATE_PERMISSION_MASK
| ENFORCE_PHONE_STATE_PERMISSION_MASK)) != 0;
r.canReadPhoneState = isPhoneStateEvent && canReadPhoneState(callingPackage);
// Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
// force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
@@ -558,7 +565,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
try {
r.callback.onCallStateChanged(mCallState[phoneId],
mCallIncomingNumber[phoneId]);
getCallIncomingNumber(r, phoneId));
} catch (RemoteException ex) {
remove(r.binder);
}
@@ -638,6 +645,22 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
private boolean canReadPhoneState(String callingPackage) {
boolean canReadPhoneState = mContext.checkCallingOrSelfPermission(
android.Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED;
if (canReadPhoneState &&
mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
callingPackage) != AppOpsManager.MODE_ALLOWED) {
return false;
}
return canReadPhoneState;
}
private String getCallIncomingNumber(Record record, int phoneId) {
// Hide the number if record's process has no READ_PHONE_STATE permission
return record.canReadPhoneState ? mCallIncomingNumber[phoneId] : "";
}
private void remove(IBinder binder) {
synchronized (mRecords) {
final int recordCount = mRecords.size();
@@ -669,7 +692,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) &&
(r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
try {
r.callback.onCallStateChanged(state, incomingNumber);
String incomingNumberOrEmpty = r.canReadPhoneState ? incomingNumber : "";
r.callback.onCallStateChanged(state, incomingNumberOrEmpty);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -699,7 +723,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
(r.subId == subId) &&
(r.subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
try {
r.callback.onCallStateChanged(state, incomingNumber);
String incomingNumberOrEmpty = getCallIncomingNumber(r, phoneId);
r.callback.onCallStateChanged(state, incomingNumberOrEmpty);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -1538,7 +1563,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
if ((events & PHONE_STATE_PERMISSION_MASK) != 0) {
if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PHONE_STATE, null);
}
@@ -1572,10 +1597,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
boolean valid = false;
try {
foregroundUser = ActivityManager.getCurrentUser();
valid = r.callerUid == foregroundUser && r.matchPhoneStateListenerEvent(events);
valid = r.callerUserId == foregroundUser && r.matchPhoneStateListenerEvent(events);
if (DBG | DBG_LOC) {
log("validateEventsAndUserLocked: valid=" + valid
+ " r.callerUid=" + r.callerUid + " foregroundUser=" + foregroundUser
+ " r.callerUserId=" + r.callerUserId + " foregroundUser=" + foregroundUser
+ " r.events=" + r.events + " events=" + events);
}
} finally {

View File

@@ -120,8 +120,7 @@ public class PhoneStateListener {
/**
* Listen for changes to the device call state.
* {@more}
* Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
* READ_PHONE_STATE}
*
* @see #onCallStateChanged
*/
public static final int LISTEN_CALL_STATE = 0x00000020;
@@ -137,8 +136,6 @@ public class PhoneStateListener {
* Listen for changes to the direction of data traffic on the data
* connection (cellular).
* {@more}
* Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
* READ_PHONE_STATE}
* Example: The status bar uses this to display the appropriate
* data-traffic icon.
*
@@ -388,6 +385,10 @@ public class PhoneStateListener {
/**
* Callback invoked when device call state changes.
* @param state call state
* @param incomingNumber incoming call phone number. If application does not have
* {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} permission, an empty
* string will be passed as an argument.
*
* @see TelephonyManager#CALL_STATE_IDLE
* @see TelephonyManager#CALL_STATE_RINGING