Merge "Do not enforce PHONE_STATE_PERMISSION to register listener" into mnc-dev

This commit is contained in:
Fyodor Kupolov
2015-06-09 19:47:29 +00:00
committed by Android (Google) Code Review
2 changed files with 56 additions and 30 deletions

View File

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

View File

@@ -120,8 +120,7 @@ public class PhoneStateListener {
/** /**
* Listen for changes to the device call state. * Listen for changes to the device call state.
* {@more} * {@more}
* Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE *
* READ_PHONE_STATE}
* @see #onCallStateChanged * @see #onCallStateChanged
*/ */
public static final int LISTEN_CALL_STATE = 0x00000020; 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 * Listen for changes to the direction of data traffic on the data
* connection (cellular). * connection (cellular).
* {@more} * {@more}
* Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
* READ_PHONE_STATE}
* Example: The status bar uses this to display the appropriate * Example: The status bar uses this to display the appropriate
* data-traffic icon. * data-traffic icon.
* *
@@ -388,6 +385,10 @@ public class PhoneStateListener {
/** /**
* Callback invoked when device call state changes. * 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_IDLE
* @see TelephonyManager#CALL_STATE_RINGING * @see TelephonyManager#CALL_STATE_RINGING