Suppress location information for non-active users.
Specifically, don't allow call backs for LISTEN_CELL_LOCATION and
LISTEN_CELL_INFO.
Bug: 7087342
Change-Id: Ida7f60b5bde3f28264dcb454b38fcfb1f1616d11
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index 8361477..26684de 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -16,14 +16,19 @@
package com.android.server;
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.LinkCapabilities;
import android.net.LinkProperties;
import android.os.Binder;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.telephony.CellLocation;
@@ -39,13 +44,11 @@
import java.util.List;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.net.NetworkInterface;
import com.android.internal.app.IBatteryStats;
import com.android.internal.telephony.ITelephonyRegistry;
import com.android.internal.telephony.IPhoneStateListener;
import com.android.internal.telephony.DefaultPhoneNotifier;
-import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.TelephonyIntents;
@@ -58,6 +61,7 @@
class TelephonyRegistry extends ITelephonyRegistry.Stub {
private static final String TAG = "TelephonyRegistry";
private static final boolean DBG = false;
+ private static final boolean DBG_LOC = false;
private static class Record {
String pkgForDebug;
@@ -66,7 +70,15 @@
IPhoneStateListener callback;
+ int callerUid;
+
int events;
+
+ @Override
+ public String toString() {
+ return "{pkgForDebug=" + pkgForDebug + " callerUid=" + callerUid +
+ " events=" + Integer.toHexString(events) + "}";
+ }
}
private final Context mContext;
@@ -120,6 +132,32 @@
PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR;
+ private static final int MSG_USER_SWITCHED = 1;
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_USER_SWITCHED: {
+ Slog.d(TAG, "MSG_USER_SWITCHED userId=" + msg.arg1);
+ TelephonyRegistry.this.notifyCellLocation(mCellLocation);
+ break;
+ }
+ }
+ }
+ };
+
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_USER_SWITCHED,
+ intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0), 0));
+ }
+ }
+ };
+
// we keep a copy of all of the state so we can send it out when folks
// register for it
//
@@ -140,10 +178,24 @@
mConnectedApns = new ArrayList<String>();
}
+ public void systemReady() {
+ // Watch for interesting updates
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_USER_SWITCHED);
+ filter.addAction(Intent.ACTION_USER_REMOVED);
+ mContext.registerReceiver(mBroadcastReceiver, filter);
+ }
+
+ @Override
public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
boolean notifyNow) {
- // Slog.d(TAG, "listen pkg=" + pkgForDebug + " events=0x" +
- // Integer.toHexString(events));
+ int callerUid = UserHandle.getCallingUserId();
+ int myUid = UserHandle.myUserId();
+ if (DBG) {
+ Slog.d(TAG, "listen: E pkg=" + pkgForDebug + " events=0x" + Integer.toHexString(events)
+ + " myUid=" + myUid
+ + " callerUid=" + callerUid);
+ }
if (events != 0) {
/* Checks permission and throws Security exception */
checkListenerPermission(events);
@@ -164,7 +216,9 @@
r.binder = b;
r.callback = callback;
r.pkgForDebug = pkgForDebug;
+ r.callerUid = callerUid;
mRecords.add(r);
+ if (DBG) Slog.i(TAG, "listen: add new record=" + r);
}
int send = events & (events ^ r.events);
r.events = events;
@@ -199,8 +253,9 @@
remove(r.binder);
}
}
- if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
+ if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
try {
+ if (DBG_LOC) Slog.d(TAG, "listen: mCellLocation=" + mCellLocation);
r.callback.onCellLocationChanged(new Bundle(mCellLocation));
} catch (RemoteException ex) {
remove(r.binder);
@@ -242,8 +297,9 @@
remove(r.binder);
}
}
- if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
+ if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
try {
+ if (DBG_LOC) Slog.d(TAG, "listen: mCellInfo=" + mCellInfo);
r.callback.onCellInfoChanged(mCellInfo);
} catch (RemoteException ex) {
remove(r.binder);
@@ -346,8 +402,11 @@
synchronized (mRecords) {
mCellInfo = cellInfo;
for (Record r : mRecords) {
- if ((r.events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
+ if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
try {
+ if (DBG_LOC) {
+ Slog.d(TAG, "notifyCellInfo: mCellInfo=" + mCellInfo + " r=" + r);
+ }
r.callback.onCellInfoChanged(cellInfo);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
@@ -424,7 +483,8 @@
if (DBG) {
Slog.i(TAG, "notifyDataConnection: state=" + state + " isDataConnectivityPossible="
+ isDataConnectivityPossible + " reason='" + reason
- + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType);
+ + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType
+ + " mRecords.size()=" + mRecords.size() + " mRecords=" + mRecords);
}
synchronized (mRecords) {
boolean modified = false;
@@ -506,8 +566,12 @@
synchronized (mRecords) {
mCellLocation = cellLocation;
for (Record r : mRecords) {
- if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
+ if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
try {
+ if (DBG_LOC) {
+ Slog.d(TAG, "notifyCellLocation: mCellLocation=" + mCellLocation
+ + " r=" + r);
+ }
r.callback.onCellLocationChanged(new Bundle(cellLocation));
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
@@ -712,4 +776,22 @@
mRemoveList.clear();
}
}
+
+ private boolean validateEventsAndUserLocked(Record r, int events) {
+ int foregroundUser;
+ long callingIdentity = Binder.clearCallingIdentity();
+ boolean valid = false;
+ try {
+ foregroundUser = ActivityManager.getCurrentUser();
+ valid = r.callerUid == foregroundUser && (r.events & events) != 0;
+ if (DBG | DBG_LOC) {
+ Slog.d(TAG, "validateEventsAndUserLocked: valid=" + valid
+ + " r.callerUid=" + r.callerUid + " foregroundUser=" + foregroundUser
+ + " r.events=" + r.events + " events=" + events);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ return valid;
+ }
}