summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/input/InputReader.cpp137
-rw-r--r--services/input/InputReader.h23
-rw-r--r--services/java/com/android/server/ConnectivityService.java7
-rw-r--r--services/java/com/android/server/LocationManagerService.java129
-rw-r--r--services/java/com/android/server/MountService.java19
-rw-r--r--services/java/com/android/server/NativeDaemonConnector.java76
-rw-r--r--services/java/com/android/server/NetworkManagementService.java6
-rw-r--r--services/java/com/android/server/NotificationManagerService.java110
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java24
-rw-r--r--services/java/com/android/server/accounts/AccountManagerService.java15
-rw-r--r--services/java/com/android/server/am/ActivityStack.java4
-rw-r--r--services/java/com/android/server/content/SyncManager.java4
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java4
-rw-r--r--services/java/com/android/server/wifi/WifiController.java117
-rw-r--r--services/java/com/android/server/wifi/WifiNotificationController.java5
-rw-r--r--services/java/com/android/server/wifi/WifiService.java14
-rw-r--r--services/jni/com_android_server_BatteryService.cpp2
-rw-r--r--services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java27
18 files changed, 508 insertions, 215 deletions
diff --git a/services/input/InputReader.cpp b/services/input/InputReader.cpp
index 3d6b6e7..c774763 100644
--- a/services/input/InputReader.cpp
+++ b/services/input/InputReader.cpp
@@ -2619,6 +2619,18 @@ void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f,
0.0f);
}
+ if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
+ const InputDeviceInfo::MotionRange& x = mOrientedRanges.x;
+ const InputDeviceInfo::MotionRange& y = mOrientedRanges.y;
+ info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_1, mSource, x.min, x.max, x.flat,
+ x.fuzz, x.resolution);
+ info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_2, mSource, y.min, y.max, y.flat,
+ y.fuzz, y.resolution);
+ info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_3, mSource, x.min, x.max, x.flat,
+ x.fuzz, x.resolution);
+ info->addMotionRange(AMOTION_EVENT_AXIS_GENERIC_4, mSource, y.min, y.max, y.flat,
+ y.fuzz, y.resolution);
+ }
}
}
@@ -2701,12 +2713,6 @@ void TouchInputMapper::dump(String8& dump) {
mPointerYZoomScale);
dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n",
mPointerGestureMaxSwipeWidth);
- } else if (mDeviceMode == DEVICE_MODE_NAVIGATION) {
- dump.appendFormat(INDENT3 "Navigation Gesture Detector:\n");
- dump.appendFormat(INDENT4 "AssistStartY: %0.3f\n",
- mNavigationAssistStartY);
- dump.appendFormat(INDENT4 "AssistEndY: %0.3f\n",
- mNavigationAssistEndY);
}
}
@@ -3278,10 +3284,6 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
// Abort current pointer usages because the state has changed.
abortPointerUsage(when, 0 /*policyFlags*/);
- } else if (mDeviceMode == DEVICE_MODE_NAVIGATION) {
- // Compute navigation parameters.
- mNavigationAssistStartY = mSurfaceHeight * 0.9f;
- mNavigationAssistEndY = mSurfaceHeight * 0.5f;
}
// Inform the dispatcher about the changes.
@@ -3458,6 +3460,19 @@ void TouchInputMapper::parseCalibration() {
out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
out.distanceScale);
+
+ out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_DEFAULT;
+ String8 coverageCalibrationString;
+ if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
+ if (coverageCalibrationString == "none") {
+ out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
+ } else if (coverageCalibrationString == "box") {
+ out.coverageCalibration = Calibration::COVERAGE_CALIBRATION_BOX;
+ } else if (coverageCalibrationString != "default") {
+ ALOGW("Invalid value for touch.coverage.calibration: '%s'",
+ coverageCalibrationString.string());
+ }
+ }
}
void TouchInputMapper::resolveCalibration() {
@@ -3496,6 +3511,11 @@ void TouchInputMapper::resolveCalibration() {
} else {
mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
}
+
+ // Coverage
+ if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_DEFAULT) {
+ mCalibration.coverageCalibration = Calibration::COVERAGE_CALIBRATION_NONE;
+ }
}
void TouchInputMapper::dumpCalibration(String8& dump) {
@@ -3588,6 +3608,17 @@ void TouchInputMapper::dumpCalibration(String8& dump) {
dump.appendFormat(INDENT4 "touch.distance.scale: %0.3f\n",
mCalibration.distanceScale);
}
+
+ switch (mCalibration.coverageCalibration) {
+ case Calibration::COVERAGE_CALIBRATION_NONE:
+ dump.append(INDENT4 "touch.coverage.calibration: none\n");
+ break;
+ case Calibration::COVERAGE_CALIBRATION_BOX:
+ dump.append(INDENT4 "touch.coverage.calibration: box\n");
+ break;
+ default:
+ ALOG_ASSERT(false);
+ }
}
void TouchInputMapper::reset(nsecs_t when) {
@@ -3621,7 +3652,6 @@ void TouchInputMapper::reset(nsecs_t when) {
mPointerGesture.reset();
mPointerSimple.reset();
- mNavigation.reset();
if (mPointerController != NULL) {
mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
@@ -3772,8 +3802,6 @@ void TouchInputMapper::sync(nsecs_t when) {
mPointerController->setSpots(mCurrentCookedPointerData.pointerCoords,
mCurrentCookedPointerData.idToIndex,
mCurrentCookedPointerData.touchingIdBits);
- } else if (mDeviceMode == DEVICE_MODE_NAVIGATION) {
- dispatchNavigationAssist(when, policyFlags);
}
dispatchHoverExit(when, policyFlags);
@@ -4198,13 +4226,31 @@ void TouchInputMapper::cookPointerData() {
distance = 0;
}
- // X and Y
+ // Coverage
+ int32_t rawLeft, rawTop, rawRight, rawBottom;
+ switch (mCalibration.coverageCalibration) {
+ case Calibration::COVERAGE_CALIBRATION_BOX:
+ rawLeft = (in.toolMinor & 0xffff0000) >> 16;
+ rawRight = in.toolMinor & 0x0000ffff;
+ rawBottom = in.toolMajor & 0x0000ffff;
+ rawTop = (in.toolMajor & 0xffff0000) >> 16;
+ break;
+ default:
+ rawLeft = rawTop = rawRight = rawBottom = 0;
+ break;
+ }
+
+ // X, Y, and the bounding box for coverage information
// Adjust coords for surface orientation.
- float x, y;
+ float x, y, left, top, right, bottom;
switch (mSurfaceOrientation) {
case DISPLAY_ORIENTATION_90:
x = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
y = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
+ left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+ right = float(rawBottom- mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+ bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
+ top = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
orientation -= M_PI_2;
if (orientation < - M_PI_2) {
orientation += M_PI;
@@ -4213,10 +4259,18 @@ void TouchInputMapper::cookPointerData() {
case DISPLAY_ORIENTATION_180:
x = float(mRawPointerAxes.x.maxValue - in.x) * mXScale + mXTranslate;
y = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
+ left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale + mXTranslate;
+ right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
+ bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
+ top = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
break;
case DISPLAY_ORIENTATION_270:
x = float(mRawPointerAxes.y.maxValue - in.y) * mYScale + mYTranslate;
y = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+ left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale + mYTranslate;
+ right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
+ bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+ top = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
orientation += M_PI_2;
if (orientation > M_PI_2) {
orientation -= M_PI;
@@ -4225,6 +4279,10 @@ void TouchInputMapper::cookPointerData() {
default:
x = float(in.x - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
y = float(in.y - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+ left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+ right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
+ bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
+ top = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
break;
}
@@ -4237,11 +4295,18 @@ void TouchInputMapper::cookPointerData() {
out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
- out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
- out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
out.setAxisValue(AMOTION_EVENT_AXIS_TILT, tilt);
out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
+ if (mCalibration.coverageCalibration == Calibration::COVERAGE_CALIBRATION_BOX) {
+ out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_1, left);
+ out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_2, top);
+ out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_3, right);
+ out.setAxisValue(AMOTION_EVENT_AXIS_GENERIC_4, bottom);
+ } else {
+ out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
+ out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
+ }
// Write output properties.
PointerProperties& properties = mCurrentCookedPointerData.pointerProperties[i];
@@ -5495,44 +5560,6 @@ void TouchInputMapper::abortPointerSimple(nsecs_t when, uint32_t policyFlags) {
dispatchPointerSimple(when, policyFlags, false, false);
}
-void TouchInputMapper::dispatchNavigationAssist(nsecs_t when, uint32_t policyFlags) {
- if (mCurrentCookedPointerData.touchingIdBits.count() == 1) {
- if (mLastCookedPointerData.touchingIdBits.isEmpty()) {
- // First pointer down.
- uint32_t id = mCurrentCookedPointerData.touchingIdBits.firstMarkedBit();
- const PointerCoords& coords = mCurrentCookedPointerData.pointerCoordsForId(id);
- if (coords.getY() >= mNavigationAssistStartY) {
- // Start tracking the possible assist swipe.
- mNavigation.activeAssistId = id;
- return;
- }
- } else if (mNavigation.activeAssistId >= 0
- && mCurrentCookedPointerData.touchingIdBits.hasBit(mNavigation.activeAssistId)) {
- const PointerCoords& coords = mCurrentCookedPointerData.pointerCoordsForId(
- mNavigation.activeAssistId);
- if (coords.getY() > mNavigationAssistEndY) {
- // Swipe is still in progress.
- return;
- }
-
- // Detected assist swipe.
- int32_t metaState = mContext->getGlobalMetaState();
- NotifyKeyArgs downArgs(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD,
- policyFlags | POLICY_FLAG_VIRTUAL,
- AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_ASSIST, 0, metaState, when);
- getListener()->notifyKey(&downArgs);
-
- NotifyKeyArgs upArgs(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD,
- policyFlags | POLICY_FLAG_VIRTUAL,
- AKEY_EVENT_ACTION_UP, 0, AKEYCODE_ASSIST, 0, metaState, when);
- getListener()->notifyKey(&upArgs);
- }
- }
-
- // Cancel the assist swipe.
- mNavigation.activeAssistId = -1;
-}
-
void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
const PointerProperties* properties, const PointerCoords* coords,
diff --git a/services/input/InputReader.h b/services/input/InputReader.h
index ed2a5c1..0189ba7 100644
--- a/services/input/InputReader.h
+++ b/services/input/InputReader.h
@@ -1267,6 +1267,14 @@ protected:
bool haveDistanceScale;
float distanceScale;
+ enum CoverageCalibration {
+ COVERAGE_CALIBRATION_DEFAULT,
+ COVERAGE_CALIBRATION_NONE,
+ COVERAGE_CALIBRATION_BOX,
+ };
+
+ CoverageCalibration coverageCalibration;
+
inline void applySizeScaleAndBias(float* outSize) const {
if (haveSizeScale) {
*outSize *= sizeScale;
@@ -1437,10 +1445,6 @@ private:
// The maximum swipe width.
float mPointerGestureMaxSwipeWidth;
- // The start and end Y thresholds for invoking the assist navigation swipe.
- float mNavigationAssistStartY;
- float mNavigationAssistEndY;
-
struct PointerDistanceHeapElement {
uint32_t currentPointerIndex : 8;
uint32_t lastPointerIndex : 8;
@@ -1615,15 +1619,6 @@ private:
}
} mPointerSimple;
- struct Navigation {
- // The id of a pointer that is tracking a possible assist swipe.
- int32_t activeAssistId; // -1 if none
-
- void reset() {
- activeAssistId = -1;
- }
- } mNavigation;
-
// The pointer and scroll velocity controls.
VelocityControl mPointerVelocityControl;
VelocityControl mWheelXVelocityControl;
@@ -1659,8 +1654,6 @@ private:
bool down, bool hovering);
void abortPointerSimple(nsecs_t when, uint32_t policyFlags);
- void dispatchNavigationAssist(nsecs_t when, uint32_t policyFlags);
-
// Dispatches a motion event.
// If the changedId is >= 0 and the action is POINTER_DOWN or POINTER_UP, the
// method will take care of setting the index and transmuting the action to DOWN or UP
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 3e19094..37a8cb8 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -2261,9 +2261,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
boolean resetDns = updateRoutes(newLp, curLp, mNetConfigs[netType].isDefault());
if (resetMask != 0 || resetDns) {
- LinkProperties linkProperties = mNetTrackers[netType].getLinkProperties();
- if (linkProperties != null) {
- for (String iface : linkProperties.getAllInterfaceNames()) {
+ if (curLp != null) {
+ for (String iface : curLp.getAllInterfaceNames()) {
if (TextUtils.isEmpty(iface) == false) {
if (resetMask != 0) {
if (DBG) log("resetConnections(" + iface + ", " + resetMask + ")");
@@ -2285,6 +2284,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (DBG) loge("Exception resetting dns cache: " + e);
}
}
+ } else {
+ loge("Can't reset connection for type "+netType);
}
}
}
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 142357d..f784030 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -135,8 +135,8 @@ public class LocationManagerService extends ILocationManager.Stub {
// --- fields below are final after systemReady() ---
private LocationFudger mLocationFudger;
private GeofenceManager mGeofenceManager;
- private PowerManager.WakeLock mWakeLock;
private PackageManager mPackageManager;
+ private PowerManager mPowerManager;
private GeocoderProxy mGeocodeProvider;
private IGpsStatusProvider mGpsStatusProvider;
private INetInitiatedListener mNetInitiatedListener;
@@ -145,9 +145,6 @@ public class LocationManagerService extends ILocationManager.Stub {
private LocationBlacklist mBlacklist;
private HandlerThread mHandlerThread;
- // --- fields below are protected by mWakeLock ---
- private int mPendingBroadcasts;
-
// --- fields below are protected by mLock ---
// Set of providers that are explicitly enabled
private final Set<String> mEnabledProviders = new HashSet<String>();
@@ -210,10 +207,8 @@ public class LocationManagerService extends ILocationManager.Stub {
// fetch package manager
mPackageManager = mContext.getPackageManager();
- // prepare wake lock
- PowerManager powerManager =
- (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
+ // fetch power manager
+ mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
// prepare worker thread
mHandlerThread = new HandlerThread(THREAD_NAME, Process.THREAD_PRIORITY_BACKGROUND);
@@ -469,6 +464,7 @@ public class LocationManagerService extends ILocationManager.Stub {
final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
int mPendingBroadcasts;
+ PowerManager.WakeLock mWakeLock;
Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
String packageName) {
@@ -483,6 +479,10 @@ public class LocationManagerService extends ILocationManager.Stub {
mUid = uid;
mPid = pid;
mPackageName = packageName;
+
+ // construct/configure wakelock
+ mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
+ mWakeLock.setWorkSource(new WorkSource(mUid, mPackageName));
}
@Override
@@ -645,10 +645,7 @@ public class LocationManagerService extends ILocationManager.Stub {
removeUpdatesLocked(this);
}
synchronized (this) {
- if (mPendingBroadcasts > 0) {
- LocationManagerService.this.decrementPendingBroadcasts();
- mPendingBroadcasts = 0;
- }
+ clearPendingBroadcastsLocked();
}
}
@@ -664,32 +661,45 @@ public class LocationManagerService extends ILocationManager.Stub {
// containing the sending of the broadcaset
private void incrementPendingBroadcastsLocked() {
if (mPendingBroadcasts++ == 0) {
- LocationManagerService.this.incrementPendingBroadcasts();
+ mWakeLock.acquire();
}
}
private void decrementPendingBroadcastsLocked() {
if (--mPendingBroadcasts == 0) {
- LocationManagerService.this.decrementPendingBroadcasts();
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
+ }
+ }
+
+ public void clearPendingBroadcastsLocked() {
+ if (mPendingBroadcasts > 0) {
+ mPendingBroadcasts = 0;
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
}
}
}
@Override
public void locationCallbackFinished(ILocationListener listener) {
- //Do not use getReceiver here as that will add the ILocationListener to
+ //Do not use getReceiverLocked here as that will add the ILocationListener to
//the receiver list if it is not found. If it is not found then the
//LocationListener was removed when it had a pending broadcast and should
//not be added back.
- IBinder binder = listener.asBinder();
- Receiver receiver = mReceivers.get(binder);
- if (receiver != null) {
- synchronized (receiver) {
- // so wakelock calls will succeed
- long identity = Binder.clearCallingIdentity();
- receiver.decrementPendingBroadcastsLocked();
- Binder.restoreCallingIdentity(identity);
- }
+ synchronized (mLock) {
+ IBinder binder = listener.asBinder();
+ Receiver receiver = mReceivers.get(binder);
+ if (receiver != null) {
+ synchronized (receiver) {
+ // so wakelock calls will succeed
+ long identity = Binder.clearCallingIdentity();
+ receiver.decrementPendingBroadcastsLocked();
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
}
}
@@ -1171,7 +1181,8 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
- private Receiver getReceiver(ILocationListener listener, int pid, int uid, String packageName) {
+ private Receiver getReceiverLocked(ILocationListener listener, int pid, int uid,
+ String packageName) {
IBinder binder = listener.asBinder();
Receiver receiver = mReceivers.get(binder);
if (receiver == null) {
@@ -1188,7 +1199,7 @@ public class LocationManagerService extends ILocationManager.Stub {
return receiver;
}
- private Receiver getReceiver(PendingIntent intent, int pid, int uid, String packageName) {
+ private Receiver getReceiverLocked(PendingIntent intent, int pid, int uid, String packageName) {
Receiver receiver = mReceivers.get(intent);
if (receiver == null) {
receiver = new Receiver(null, intent, pid, uid, packageName);
@@ -1252,7 +1263,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
}
- private Receiver checkListenerOrIntent(ILocationListener listener, PendingIntent intent,
+ private Receiver checkListenerOrIntentLocked(ILocationListener listener, PendingIntent intent,
int pid, int uid, String packageName) {
if (intent == null && listener == null) {
throw new IllegalArgumentException("need either listener or intent");
@@ -1260,9 +1271,9 @@ public class LocationManagerService extends ILocationManager.Stub {
throw new IllegalArgumentException("cannot register both listener and intent");
} else if (intent != null) {
checkPendingIntent(intent);
- return getReceiver(intent, pid, uid, packageName);
+ return getReceiverLocked(intent, pid, uid, packageName);
} else {
- return getReceiver(listener, pid, uid, packageName);
+ return getReceiverLocked(listener, pid, uid, packageName);
}
}
@@ -1284,9 +1295,10 @@ public class LocationManagerService extends ILocationManager.Stub {
// We don't check for MODE_IGNORED here; we will do that when we go to deliver
// a location.
checkLocationAccess(uid, packageName, allowedResolutionLevel);
- Receiver recevier = checkListenerOrIntent(listener, intent, pid, uid, packageName);
synchronized (mLock) {
+ Receiver recevier = checkListenerOrIntentLocked(listener, intent, pid, uid,
+ packageName);
requestLocationUpdatesLocked(sanitizedRequest, recevier, pid, uid, packageName);
}
} finally {
@@ -1333,16 +1345,17 @@ public class LocationManagerService extends ILocationManager.Stub {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
- Receiver receiver = checkListenerOrIntent(listener, intent, pid, uid, packageName);
- // providers may use public location API's, need to clear identity
- long identity = Binder.clearCallingIdentity();
- try {
- synchronized (mLock) {
+ synchronized (mLock) {
+ Receiver receiver = checkListenerOrIntentLocked(listener, intent, pid, uid, packageName);
+
+ // providers may use public location API's, need to clear identity
+ long identity = Binder.clearCallingIdentity();
+ try {
removeUpdatesLocked(receiver);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
}
- } finally {
- Binder.restoreCallingIdentity(identity);
}
}
@@ -1352,10 +1365,7 @@ public class LocationManagerService extends ILocationManager.Stub {
if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
synchronized (receiver) {
- if (receiver.mPendingBroadcasts > 0) {
- decrementPendingBroadcasts();
- receiver.mPendingBroadcasts = 0;
- }
+ receiver.clearPendingBroadcastsLocked();
}
}
@@ -1957,43 +1967,6 @@ public class LocationManagerService extends ILocationManager.Stub {
}
};
- // Wake locks
-
- private void incrementPendingBroadcasts() {
- synchronized (mWakeLock) {
- if (mPendingBroadcasts++ == 0) {
- try {
- mWakeLock.acquire();
- log("Acquired wakelock");
- } catch (Exception e) {
- // This is to catch a runtime exception thrown when we try to release an
- // already released lock.
- Slog.e(TAG, "exception in acquireWakeLock()", e);
- }
- }
- }
- }
-
- private void decrementPendingBroadcasts() {
- synchronized (mWakeLock) {
- if (--mPendingBroadcasts == 0) {
- try {
- // Release wake lock
- if (mWakeLock.isHeld()) {
- mWakeLock.release();
- log("Released wakelock");
- } else {
- log("Can't release wakelock again!");
- }
- } catch (Exception e) {
- // This is to catch a runtime exception thrown when we try to release an
- // already released lock.
- Slog.e(TAG, "exception in releaseWakeLock()", e);
- }
- }
- }
- }
-
// Geocoder
@Override
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index d7adbf7..f402f4b 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -64,6 +64,7 @@ import com.android.internal.app.IMediaContainerService;
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.NativeDaemonConnector.Command;
+import com.android.server.NativeDaemonConnector.SensitiveArg;
import com.android.server.am.ActivityManagerService;
import com.android.server.pm.PackageManagerService;
import com.android.server.pm.UserManagerService;
@@ -1642,8 +1643,8 @@ class MountService extends IMountService.Stub
int rc = StorageResultCode.OperationSucceeded;
try {
- mConnector.execute("asec", "create", id, sizeMb, fstype, key, ownerUid,
- external ? "1" : "0");
+ mConnector.execute("asec", "create", id, sizeMb, fstype, new SensitiveArg(key),
+ ownerUid, external ? "1" : "0");
} catch (NativeDaemonConnectorException e) {
rc = StorageResultCode.OperationFailedInternalError;
}
@@ -1743,7 +1744,7 @@ class MountService extends IMountService.Stub
int rc = StorageResultCode.OperationSucceeded;
try {
- mConnector.execute("asec", "mount", id, key, ownerUid);
+ mConnector.execute("asec", "mount", id, new SensitiveArg(key), ownerUid);
} catch (NativeDaemonConnectorException e) {
int code = e.getCode();
if (code != VoldResponseCode.OpFailedStorageBusy) {
@@ -2019,7 +2020,7 @@ class MountService extends IMountService.Stub
final NativeDaemonEvent event;
try {
- event = mConnector.execute("cryptfs", "checkpw", password);
+ event = mConnector.execute("cryptfs", "checkpw", new SensitiveArg(password));
final int code = Integer.parseInt(event.getMessage());
if (code == 0) {
@@ -2058,7 +2059,7 @@ class MountService extends IMountService.Stub
}
try {
- mConnector.execute("cryptfs", "enablecrypto", "inplace", password);
+ mConnector.execute("cryptfs", "enablecrypto", "inplace", new SensitiveArg(password));
} catch (NativeDaemonConnectorException e) {
// Encryption failed
return e.getCode();
@@ -2083,7 +2084,7 @@ class MountService extends IMountService.Stub
final NativeDaemonEvent event;
try {
- event = mConnector.execute("cryptfs", "changepw", password);
+ event = mConnector.execute("cryptfs", "changepw", new SensitiveArg(password));
return Integer.parseInt(event.getMessage());
} catch (NativeDaemonConnectorException e) {
// Encryption failed
@@ -2116,7 +2117,7 @@ class MountService extends IMountService.Stub
final NativeDaemonEvent event;
try {
- event = mConnector.execute("cryptfs", "verifypw", password);
+ event = mConnector.execute("cryptfs", "verifypw", new SensitiveArg(password));
Slog.i(TAG, "cryptfs verifypw => " + event.getMessage());
return Integer.parseInt(event.getMessage());
} catch (NativeDaemonConnectorException e) {
@@ -2482,8 +2483,8 @@ class MountService extends IMountService.Stub
int rc = StorageResultCode.OperationSucceeded;
try {
- mConnector.execute(
- "obb", "mount", mObbState.voldPath, hashedKey, mObbState.ownerGid);
+ mConnector.execute("obb", "mount", mObbState.voldPath, new SensitiveArg(hashedKey),
+ mObbState.ownerGid);
} catch (NativeDaemonConnectorException e) {
int code = e.getCode();
if (code != VoldResponseCode.OpFailedStorageBusy) {
diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java
index c3f2afa..47840e0 100644
--- a/services/java/com/android/server/NativeDaemonConnector.java
+++ b/services/java/com/android/server/NativeDaemonConnector.java
@@ -204,9 +204,28 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
}
/**
+ * Wrapper around argument that indicates it's sensitive and shouldn't be
+ * logged.
+ */
+ public static class SensitiveArg {
+ private final Object mArg;
+
+ public SensitiveArg(Object arg) {
+ mArg = arg;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(mArg);
+ }
+ }
+
+ /**
* Make command for daemon, escaping arguments as needed.
*/
- private void makeCommand(StringBuilder builder, String cmd, Object... args) {
+ @VisibleForTesting
+ static void makeCommand(StringBuilder rawBuilder, StringBuilder logBuilder, int sequenceNumber,
+ String cmd, Object... args) {
if (cmd.indexOf('\0') >= 0) {
throw new IllegalArgumentException("Unexpected command: " + cmd);
}
@@ -214,16 +233,26 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
throw new IllegalArgumentException("Arguments must be separate from command");
}
- builder.append(cmd);
+ rawBuilder.append(sequenceNumber).append(' ').append(cmd);
+ logBuilder.append(sequenceNumber).append(' ').append(cmd);
for (Object arg : args) {
final String argString = String.valueOf(arg);
if (argString.indexOf('\0') >= 0) {
throw new IllegalArgumentException("Unexpected argument: " + arg);
}
- builder.append(' ');
- appendEscaped(builder, argString);
+ rawBuilder.append(' ');
+ logBuilder.append(' ');
+
+ appendEscaped(rawBuilder, argString);
+ if (arg instanceof SensitiveArg) {
+ logBuilder.append("[scrubbed]");
+ } else {
+ appendEscaped(logBuilder, argString);
+ }
}
+
+ rawBuilder.append('\0');
}
/**
@@ -303,27 +332,27 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
*/
public NativeDaemonEvent[] execute(int timeout, String cmd, Object... args)
throws NativeDaemonConnectorException {
+ final long startTime = SystemClock.elapsedRealtime();
+
final ArrayList<NativeDaemonEvent> events = Lists.newArrayList();
+ final StringBuilder rawBuilder = new StringBuilder();
+ final StringBuilder logBuilder = new StringBuilder();
final int sequenceNumber = mSequenceNumber.incrementAndGet();
- final StringBuilder cmdBuilder =
- new StringBuilder(Integer.toString(sequenceNumber)).append(' ');
- final long startTime = SystemClock.elapsedRealtime();
- makeCommand(cmdBuilder, cmd, args);
+ makeCommand(rawBuilder, logBuilder, sequenceNumber, cmd, args);
- final String logCmd = cmdBuilder.toString(); /* includes cmdNum, cmd, args */
- log("SND -> {" + logCmd + "}");
+ final String rawCmd = rawBuilder.toString();
+ final String logCmd = logBuilder.toString();
- cmdBuilder.append('\0');
- final String sentCmd = cmdBuilder.toString(); /* logCmd + \0 */
+ log("SND -> {" + logCmd + "}");
synchronized (mDaemonLock) {
if (mOutputStream == null) {
throw new NativeDaemonConnectorException("missing output stream");
} else {
try {
- mOutputStream.write(sentCmd.getBytes(Charsets.UTF_8));
+ mOutputStream.write(rawCmd.getBytes(Charsets.UTF_8));
} catch (IOException e) {
throw new NativeDaemonConnectorException("problem sending command", e);
}
@@ -332,7 +361,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
NativeDaemonEvent event = null;
do {
- event = mResponseQueue.remove(sequenceNumber, timeout, sentCmd);
+ event = mResponseQueue.remove(sequenceNumber, timeout, logCmd);
if (event == null) {
loge("timed-out waiting for response to " + logCmd);
throw new NativeDaemonFailureException(logCmd, event);
@@ -447,10 +476,11 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
private static class ResponseQueue {
private static class PendingCmd {
- public int cmdNum;
+ public final int cmdNum;
+ public final String logCmd;
+
public BlockingQueue<NativeDaemonEvent> responses =
new ArrayBlockingQueue<NativeDaemonEvent>(10);
- public String request;
// The availableResponseCount member is used to track when we can remove this
// instance from the ResponseQueue.
@@ -468,7 +498,11 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
// hold references to this instance already so it can be removed from
// mPendingCmds queue.
public int availableResponseCount;
- public PendingCmd(int c, String r) {cmdNum = c; request = r;}
+
+ public PendingCmd(int cmdNum, String logCmd) {
+ this.cmdNum = cmdNum;
+ this.logCmd = logCmd;
+ }
}
private final LinkedList<PendingCmd> mPendingCmds;
@@ -497,7 +531,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
// let any waiter timeout waiting for this
PendingCmd pendingCmd = mPendingCmds.remove();
Slog.e("NativeDaemonConnector.ResponseQueue",
- "Removing request: " + pendingCmd.request + " (" +
+ "Removing request: " + pendingCmd.logCmd + " (" +
pendingCmd.cmdNum + ")");
}
found = new PendingCmd(cmdNum, null);
@@ -515,7 +549,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
// note that the timeout does not count time in deep sleep. If you don't want
// the device to sleep, hold a wakelock
- public NativeDaemonEvent remove(int cmdNum, int timeoutMs, String origCmd) {
+ public NativeDaemonEvent remove(int cmdNum, int timeoutMs, String logCmd) {
PendingCmd found = null;
synchronized (mPendingCmds) {
for (PendingCmd pendingCmd : mPendingCmds) {
@@ -525,7 +559,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
}
}
if (found == null) {
- found = new PendingCmd(cmdNum, origCmd);
+ found = new PendingCmd(cmdNum, logCmd);
mPendingCmds.add(found);
}
found.availableResponseCount--;
@@ -547,7 +581,7 @@ final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdo
pw.println("Pending requests:");
synchronized (mPendingCmds) {
for (PendingCmd pendingCmd : mPendingCmds) {
- pw.println(" Cmd " + pendingCmd.cmdNum + " - " + pendingCmd.request);
+ pw.println(" Cmd " + pendingCmd.cmdNum + " - " + pendingCmd.logCmd);
}
}
}
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index d2acb40..3b84c732 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -34,7 +34,6 @@ import static com.android.server.NetworkManagementService.NetdResponseCode.Tethe
import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
-import android.bluetooth.BluetoothTetheringDataTracker;
import android.content.Context;
import android.net.INetworkManagementEventObserver;
import android.net.InterfaceConfiguration;
@@ -59,6 +58,7 @@ import android.util.SparseBooleanArray;
import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.util.Preconditions;
import com.android.server.NativeDaemonConnector.Command;
+import com.android.server.NativeDaemonConnector.SensitiveArg;
import com.android.server.net.LockdownVpnTracker;
import com.google.android.collect.Maps;
@@ -990,7 +990,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
mConnector.execute("softap", "set", wlanIface);
} else {
mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
- getSecurityType(wifiConfig), wifiConfig.preSharedKey);
+ getSecurityType(wifiConfig), new SensitiveArg(wifiConfig.preSharedKey));
}
mConnector.execute("softap", "startap");
} catch (NativeDaemonConnectorException e) {
@@ -1039,7 +1039,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
mConnector.execute("softap", "set", wlanIface);
} else {
mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
- getSecurityType(wifiConfig), wifiConfig.preSharedKey);
+ getSecurityType(wifiConfig), new SensitiveArg(wifiConfig.preSharedKey));
}
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 6a1ef45..29aaeaf 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -40,6 +40,8 @@ import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -88,7 +90,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.NoSuchElementException;
+import java.util.Set;
import libcore.io.IoUtils;
@@ -283,13 +287,14 @@ public class NotificationManagerService extends INotificationManager.Stub
}
public void record(StatusBarNotification nr) {
- // Nuke heavy parts of notification before storing in archive
- nr.getNotification().lightenPayload();
-
if (mBuffer.size() == BUFFER_SIZE) {
mBuffer.removeFirst();
}
- mBuffer.addLast(nr);
+
+ // We don't want to store the heavy bits of the notification in the archive,
+ // but other clients in the system process might be using the object, so we
+ // store a (lightened) copy.
+ mBuffer.addLast(nr.cloneLight());
}
@@ -533,6 +538,60 @@ public class NotificationManagerService extends INotificationManager.Stub
}
/**
+ * Remove notification access for any services that no longer exist.
+ */
+ void disableNonexistentListeners() {
+ int currentUser = ActivityManager.getCurrentUser();
+ String flatIn = Settings.Secure.getStringForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
+ currentUser);
+ if (!TextUtils.isEmpty(flatIn)) {
+ if (DBG) Slog.v(TAG, "flat before: " + flatIn);
+ PackageManager pm = mContext.getPackageManager();
+ List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
+ new Intent(NotificationListenerService.SERVICE_INTERFACE),
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
+ currentUser);
+
+ Set<ComponentName> installed = new HashSet<ComponentName>();
+ for (int i = 0, count = installedServices.size(); i < count; i++) {
+ ResolveInfo resolveInfo = installedServices.get(i);
+ ServiceInfo info = resolveInfo.serviceInfo;
+
+ if (!android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE.equals(
+ info.permission)) {
+ Slog.w(TAG, "Skipping notification listener service "
+ + info.packageName + "/" + info.name
+ + ": it does not require the permission "
+ + android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
+ continue;
+ }
+ installed.add(new ComponentName(info.packageName, info.name));
+ }
+
+ String flatOut = "";
+ if (!installed.isEmpty()) {
+ String[] enabled = flatIn.split(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR);
+ ArrayList<String> remaining = new ArrayList<String>(enabled.length);
+ for (int i = 0; i < enabled.length; i++) {
+ ComponentName enabledComponent = ComponentName.unflattenFromString(enabled[i]);
+ if (installed.contains(enabledComponent)) {
+ remaining.add(enabled[i]);
+ }
+ }
+ flatOut = TextUtils.join(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR, remaining);
+ }
+ if (DBG) Slog.v(TAG, "flat after: " + flatOut);
+ if (!flatIn.equals(flatOut)) {
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
+ flatOut, currentUser);
+ }
+ }
+ }
+
+ /**
* Called whenever packages change, the user switches, or ENABLED_NOTIFICATION_LISTENERS
* is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
*/
@@ -704,7 +763,8 @@ public class NotificationManagerService extends INotificationManager.Stub
final int N = mListeners.size();
for (int i=N-1; i>=0; i--) {
final NotificationListenerInfo info = mListeners.get(i);
- if (info.listener == listener && info.userid == userid) {
+ if (info.listener.asBinder() == listener.asBinder()
+ && info.userid == userid) {
mListeners.remove(i);
if (info.connection != null) {
mContext.unbindService(info.connection);
@@ -1073,15 +1133,20 @@ public class NotificationManagerService extends INotificationManager.Stub
String action = intent.getAction();
boolean queryRestart = false;
+ boolean queryRemove = false;
boolean packageChanged = false;
+ boolean cancelNotifications = true;
if (action.equals(Intent.ACTION_PACKAGE_ADDED)
- || action.equals(Intent.ACTION_PACKAGE_REMOVED)
+ || (queryRemove=action.equals(Intent.ACTION_PACKAGE_REMOVED))
|| action.equals(Intent.ACTION_PACKAGE_RESTARTED)
|| (packageChanged=action.equals(Intent.ACTION_PACKAGE_CHANGED))
|| (queryRestart=action.equals(Intent.ACTION_QUERY_PACKAGE_RESTART))
|| action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
String pkgList[] = null;
+ boolean queryReplace = queryRemove &&
+ intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+ if (DBG) Slog.i(TAG, "queryReplace=" + queryReplace);
if (action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
} else if (queryRestart) {
@@ -1101,7 +1166,7 @@ public class NotificationManagerService extends INotificationManager.Stub
.getApplicationEnabledSetting(pkgName);
if (enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
|| enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
- return;
+ cancelNotifications = false;
}
}
pkgList = new String[]{pkgName};
@@ -1110,8 +1175,10 @@ public class NotificationManagerService extends INotificationManager.Stub
boolean anyListenersInvolved = false;
if (pkgList != null && (pkgList.length > 0)) {
for (String pkgName : pkgList) {
- cancelAllNotificationsInt(pkgName, 0, 0, !queryRestart,
- UserHandle.USER_ALL);
+ if (cancelNotifications) {
+ cancelAllNotificationsInt(pkgName, 0, 0, !queryRestart,
+ UserHandle.USER_ALL);
+ }
if (mEnabledListenerPackageNames.contains(pkgName)) {
anyListenersInvolved = true;
}
@@ -1119,6 +1186,10 @@ public class NotificationManagerService extends INotificationManager.Stub
}
if (anyListenersInvolved) {
+ // if we're not replacing a package, clean up orphaned bits
+ if (!queryReplace) {
+ disableNonexistentListeners();
+ }
// make sure we're still bound to any of our
// listeners who may have just upgraded
rebindListenerServices();
@@ -1319,7 +1390,7 @@ public class NotificationManagerService extends INotificationManager.Stub
return ;
}
- final boolean isSystemToast = ("android".equals(pkg));
+ final boolean isSystemToast = isCallerSystem() || ("android".equals(pkg));
if (ENABLE_BLOCKED_TOASTS && !noteNotificationOp(pkg, Binder.getCallingUid())) {
if (!isSystemToast) {
@@ -1535,7 +1606,7 @@ public class NotificationManagerService extends INotificationManager.Stub
Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id + " notification=" + notification);
}
checkCallerIsSystemOrSameApp(pkg);
- final boolean isSystemNotification = ("android".equals(pkg));
+ final boolean isSystemNotification = isCallerSystem() || ("android".equals(pkg));
userId = ActivityManager.handleIncomingUser(callingPid,
callingUid, userId, true, false, "enqueueNotification", pkg);
@@ -2013,19 +2084,26 @@ public class NotificationManagerService extends INotificationManager.Stub
cancelAllNotificationsInt(pkg, 0, Notification.FLAG_FOREGROUND_SERVICE, true, userId);
}
+ // Return true if the caller is a system or phone UID and therefore should not have
+ // any notifications or toasts blocked.
+ boolean isCallerSystem() {
+ final int uid = Binder.getCallingUid();
+ final int appid = UserHandle.getAppId(uid);
+ return (appid == Process.SYSTEM_UID || appid == Process.PHONE_UID || uid == 0);
+ }
+
void checkCallerIsSystem() {
- int uid = Binder.getCallingUid();
- if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
+ if (isCallerSystem()) {
return;
}
- throw new SecurityException("Disallowed call for uid " + uid);
+ throw new SecurityException("Disallowed call for uid " + Binder.getCallingUid());
}
void checkCallerIsSystemOrSameApp(String pkg) {
- int uid = Binder.getCallingUid();
- if (UserHandle.getAppId(uid) == Process.SYSTEM_UID || uid == 0) {
+ if (isCallerSystem()) {
return;
}
+ final int uid = Binder.getCallingUid();
try {
ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo(
pkg, 0, UserHandle.getCallingUserId());
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 2b5544b..2f8250f 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -95,6 +95,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -405,7 +406,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
synchronized (mLock) {
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
- return getUserStateLocked(resolvedUserId).mInstalledServices;
+ // The automation service is a fake one and should not be reported
+ // to clients as being installed - it really is not.
+ UserState userState = getUserStateLocked(resolvedUserId);
+ if (userState.mUiAutomationService != null) {
+ List<AccessibilityServiceInfo> installedServices =
+ new ArrayList<AccessibilityServiceInfo>();
+ installedServices.addAll(userState.mInstalledServices);
+ installedServices.remove(userState.mUiAutomationService);
+ return installedServices;
+ }
+ return userState.mInstalledServices;
}
}
@@ -415,9 +426,18 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
synchronized (mLock) {
final int resolvedUserId = mSecurityPolicy
.resolveCallingUserIdEnforcingPermissionsLocked(userId);
+
+ // The automation service is a fake one and should not be reported
+ // to clients as being enabled. The automation service is always the
+ // only active one, if it exists.
+ UserState userState = getUserStateLocked(resolvedUserId);
+ if (userState.mUiAutomationService != null) {
+ return Collections.emptyList();
+ }
+
result = mEnabledServicesForFeedbackTempList;
result.clear();
- List<Service> services = getUserStateLocked(resolvedUserId).mBoundServices;
+ List<Service> services = userState.mBoundServices;
while (feedbackType != 0) {
final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackType));
feedbackType &= ~feedbackTypeBit;
diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/java/com/android/server/accounts/AccountManagerService.java
index 3b63937..0fbde37 100644
--- a/services/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/java/com/android/server/accounts/AccountManagerService.java
@@ -2802,12 +2802,19 @@ public class AccountManagerService
if (sharedAccounts == null || sharedAccounts.length == 0) return unfiltered;
String requiredAccountType = "";
try {
- for (String packageName : packages) {
- PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0);
+ // If there's an explicit callingPackage specified, check if that package
+ // opted in to see restricted accounts.
+ if (callingPackage != null) {
+ PackageInfo pi = mPackageManager.getPackageInfo(callingPackage, 0);
if (pi != null && pi.restrictedAccountType != null) {
requiredAccountType = pi.restrictedAccountType;
- // If it matches the package name of the original caller, use this choice.
- if (callingPackage != null && packageName.equals(callingPackage)) {
+ }
+ } else {
+ // Otherwise check if the callingUid has a package that has opted in
+ for (String packageName : packages) {
+ PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0);
+ if (pi != null && pi.restrictedAccountType != null) {
+ requiredAccountType = pi.restrictedAccountType;
break;
}
}
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 0f1700d..c344023 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -3655,7 +3655,9 @@ final class ActivityStack {
}
if (activityRemoved) {
- resumeTopActivityLocked(null);
+ synchronized (mService) {
+ resumeTopActivityLocked(null);
+ }
}
return res;
diff --git a/services/java/com/android/server/content/SyncManager.java b/services/java/com/android/server/content/SyncManager.java
index 1c883ec..ff1281e 100644
--- a/services/java/com/android/server/content/SyncManager.java
+++ b/services/java/com/android/server/content/SyncManager.java
@@ -1971,6 +1971,10 @@ public class SyncManager {
for (int i = 0, N = info.periodicSyncs.size(); i < N; i++) {
final Bundle extras = info.periodicSyncs.get(i).first;
final Long periodInMillis = info.periodicSyncs.get(i).second * 1000;
+ // Skip if the period is invalid
+ if (periodInMillis <= 0) {
+ continue;
+ }
// find when this periodic sync was last scheduled to run
final long lastPollTimeAbsolute = status.getPeriodicSyncTime(i);
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 1a0455c..22ce284 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -8120,7 +8120,7 @@ public class PackageManagerService extends IPackageManager.Stub {
allUsers = sUserManager.getUserIds();
perUserInstalled = new boolean[allUsers.length];
for (int i = 0; i < allUsers.length; i++) {
- perUserInstalled[i] = ps.getInstalled(allUsers[i]);
+ perUserInstalled[i] = ps != null ? ps.getInstalled(allUsers[i]) : false;
}
}
boolean sysPkg = (isSystemApp(oldPackage));
@@ -8689,7 +8689,7 @@ public class PackageManagerService extends IPackageManager.Stub {
allUsers = sUserManager.getUserIds();
perUserInstalled = new boolean[allUsers.length];
for (int i = 0; i < allUsers.length; i++) {
- perUserInstalled[i] = ps.getInstalled(allUsers[i]);
+ perUserInstalled[i] = ps != null ? ps.getInstalled(allUsers[i]) : false;
}
}
diff --git a/services/java/com/android/server/wifi/WifiController.java b/services/java/com/android/server/wifi/WifiController.java
index 6e6b8cc..87b4394 100644
--- a/services/java/com/android/server/wifi/WifiController.java
+++ b/services/java/com/android/server/wifi/WifiController.java
@@ -34,6 +34,7 @@ import android.net.wifi.WifiStateMachine;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.SystemClock;
import android.os.WorkSource;
import android.provider.Settings;
import android.util.Slog;
@@ -70,6 +71,17 @@ class WifiController extends StateMachine {
*/
private static final long DEFAULT_IDLE_MS = 15 * 60 * 1000; /* 15 minutes */
+ /**
+ * See {@link Settings.Global#WIFI_REENABLE_DELAY_MS}. This is the default value if a
+ * Settings.Global value is not present. This is the minimum time after wifi is disabled
+ * we'll act on an enable. Enable requests received before this delay will be deferred.
+ */
+ private static final long DEFAULT_REENABLE_DELAY_MS = 500;
+
+ // finding that delayed messages can sometimes be delivered earlier than expected
+ // probably rounding errors.. add a margin to prevent problems
+ private static final long DEFER_MARGIN_MS = 5;
+
NetworkInfo mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, "WIFI", "");
private static final String ACTION_DEVICE_IDLE =
@@ -86,6 +98,8 @@ class WifiController extends StateMachine {
*/
private final WorkSource mTmpWorkSource = new WorkSource();
+ private long mReEnableDelayMillis;
+
private static final int BASE = Protocol.BASE_WIFI_CONTROLLER;
static final int CMD_EMERGENCY_MODE_CHANGED = BASE + 1;
@@ -98,6 +112,7 @@ class WifiController extends StateMachine {
static final int CMD_WIFI_TOGGLED = BASE + 8;
static final int CMD_AIRPLANE_TOGGLED = BASE + 9;
static final int CMD_SET_AP = BASE + 10;
+ static final int CMD_DEFERRED_TOGGLE = BASE + 11;
private DefaultState mDefaultState = new DefaultState();
private StaEnabledState mStaEnabledState = new StaEnabledState();
@@ -135,9 +150,13 @@ class WifiController extends StateMachine {
addState(mStaDisabledWithScanState, mDefaultState);
addState(mApEnabledState, mDefaultState);
addState(mEcmState, mDefaultState);
- setInitialState(mApStaDisabledState);
- setLogRecSize(25);
- setLogOnlyTransitions(true);
+ if (mSettingsStore.isScanAlwaysAvailable()) {
+ setInitialState(mStaDisabledWithScanState);
+ } else {
+ setInitialState(mApStaDisabledState);
+ }
+ setLogRecSize(100);
+ setLogOnlyTransitions(false);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_DEVICE_IDLE);
@@ -168,6 +187,7 @@ class WifiController extends StateMachine {
registerForWifiIdleTimeChange(handler);
readWifiSleepPolicy();
registerForWifiSleepPolicyChange(handler);
+ readWifiReEnableDelay();
}
private void readStayAwakeConditions() {
@@ -186,6 +206,11 @@ class WifiController extends StateMachine {
Settings.Global.WIFI_SLEEP_POLICY_NEVER);
}
+ private void readWifiReEnableDelay() {
+ mReEnableDelayMillis = Settings.Global.getLong(mContext.getContentResolver(),
+ Settings.Global.WIFI_REENABLE_DELAY_MS, DEFAULT_REENABLE_DELAY_MS);
+ }
+
/**
* Observes settings changes to scan always mode.
*/
@@ -336,6 +361,9 @@ class WifiController extends StateMachine {
case CMD_AIRPLANE_TOGGLED:
case CMD_EMERGENCY_MODE_CHANGED:
break;
+ case CMD_DEFERRED_TOGGLE:
+ log("DEFERRED_TOGGLE ignored due to state change");
+ break;
default:
throw new RuntimeException("WifiController.handleMessage " + msg.what);
}
@@ -345,9 +373,17 @@ class WifiController extends StateMachine {
}
class ApStaDisabledState extends State {
+ private int mDeferredEnableSerialNumber = 0;
+ private boolean mHaveDeferredEnable = false;
+ private long mDisabledTimestamp;
+
@Override
public void enter() {
mWifiStateMachine.setSupplicantRunning(false);
+ // Supplicant can't restart right away, so not the time we switched off
+ mDisabledTimestamp = SystemClock.elapsedRealtime();
+ mDeferredEnableSerialNumber++;
+ mHaveDeferredEnable = false;
}
@Override
public boolean processMessage(Message msg) {
@@ -355,6 +391,14 @@ class WifiController extends StateMachine {
case CMD_WIFI_TOGGLED:
case CMD_AIRPLANE_TOGGLED:
if (mSettingsStore.isWifiToggleEnabled()) {
+ if (doDeferEnable(msg)) {
+ if (mHaveDeferredEnable) {
+ // have 2 toggles now, inc serial number an ignore both
+ mDeferredEnableSerialNumber++;
+ }
+ mHaveDeferredEnable = !mHaveDeferredEnable;
+ break;
+ }
if (mDeviceIdle == false) {
transitionTo(mDeviceActiveState);
} else {
@@ -374,12 +418,37 @@ class WifiController extends StateMachine {
transitionTo(mApEnabledState);
}
break;
+ case CMD_DEFERRED_TOGGLE:
+ if (msg.arg1 != mDeferredEnableSerialNumber) {
+ log("DEFERRED_TOGGLE ignored due to serial mismatch");
+ break;
+ }
+ log("DEFERRED_TOGGLE handled");
+ sendMessage((Message)(msg.obj));
+ break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
+ private boolean doDeferEnable(Message msg) {
+ long delaySoFar = SystemClock.elapsedRealtime() - mDisabledTimestamp;
+ if (delaySoFar >= mReEnableDelayMillis) {
+ return false;
+ }
+
+ log("WifiController msg " + msg + " deferred for " +
+ (mReEnableDelayMillis - delaySoFar) + "ms");
+
+ // need to defer this action.
+ Message deferredMsg = obtainMessage(CMD_DEFERRED_TOGGLE);
+ deferredMsg.obj = Message.obtain(msg);
+ deferredMsg.arg1 = ++mDeferredEnableSerialNumber;
+ sendMessageDelayed(deferredMsg, mReEnableDelayMillis - delaySoFar + DEFER_MARGIN_MS);
+ return true;
+ }
+
}
class StaEnabledState extends State {
@@ -421,11 +490,19 @@ class WifiController extends StateMachine {
}
class StaDisabledWithScanState extends State {
+ private int mDeferredEnableSerialNumber = 0;
+ private boolean mHaveDeferredEnable = false;
+ private long mDisabledTimestamp;
+
@Override
public void enter() {
mWifiStateMachine.setSupplicantRunning(true);
mWifiStateMachine.setOperationalMode(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE);
mWifiStateMachine.setDriverStart(true);
+ // Supplicant can't restart right away, so not the time we switched off
+ mDisabledTimestamp = SystemClock.elapsedRealtime();
+ mDeferredEnableSerialNumber++;
+ mHaveDeferredEnable = false;
}
@Override
@@ -433,6 +510,14 @@ class WifiController extends StateMachine {
switch (msg.what) {
case CMD_WIFI_TOGGLED:
if (mSettingsStore.isWifiToggleEnabled()) {
+ if (doDeferEnable(msg)) {
+ if (mHaveDeferredEnable) {
+ // have 2 toggles now, inc serial number and ignore both
+ mDeferredEnableSerialNumber++;
+ }
+ mHaveDeferredEnable = !mHaveDeferredEnable;
+ break;
+ }
if (mDeviceIdle == false) {
transitionTo(mDeviceActiveState);
} else {
@@ -457,11 +542,37 @@ class WifiController extends StateMachine {
transitionTo(mApStaDisabledState);
}
break;
+ case CMD_DEFERRED_TOGGLE:
+ if (msg.arg1 != mDeferredEnableSerialNumber) {
+ log("DEFERRED_TOGGLE ignored due to serial mismatch");
+ break;
+ }
+ logd("DEFERRED_TOGGLE handled");
+ sendMessage((Message)(msg.obj));
+ break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
+
+ private boolean doDeferEnable(Message msg) {
+ long delaySoFar = SystemClock.elapsedRealtime() - mDisabledTimestamp;
+ if (delaySoFar >= mReEnableDelayMillis) {
+ return false;
+ }
+
+ log("WifiController msg " + msg + " deferred for " +
+ (mReEnableDelayMillis - delaySoFar) + "ms");
+
+ // need to defer this action.
+ Message deferredMsg = obtainMessage(CMD_DEFERRED_TOGGLE);
+ deferredMsg.obj = Message.obtain(msg);
+ deferredMsg.arg1 = ++mDeferredEnableSerialNumber;
+ sendMessageDelayed(deferredMsg, mReEnableDelayMillis - delaySoFar + DEFER_MARGIN_MS);
+ return true;
+ }
+
}
class ApEnabledState extends State {
diff --git a/services/java/com/android/server/wifi/WifiNotificationController.java b/services/java/com/android/server/wifi/WifiNotificationController.java
index 17ef7c8..a9206e0 100644
--- a/services/java/com/android/server/wifi/WifiNotificationController.java
+++ b/services/java/com/android/server/wifi/WifiNotificationController.java
@@ -91,10 +91,12 @@ final class WifiNotificationController {
private final Context mContext;
private final WifiStateMachine mWifiStateMachine;
private NetworkInfo mNetworkInfo;
+ private volatile int mWifiState;
WifiNotificationController(Context context, WifiStateMachine wsm) {
mContext = context;
mWifiStateMachine = wsm;
+ mWifiState = WifiManager.WIFI_STATE_UNKNOWN;
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
@@ -106,6 +108,8 @@ final class WifiNotificationController {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
+ mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
+ WifiManager.WIFI_STATE_UNKNOWN);
resetNotification();
} else if (intent.getAction().equals(
WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
@@ -141,6 +145,7 @@ final class WifiNotificationController {
// don't bother doing any of the following
if (!mNotificationEnabled) return;
if (networkInfo == null) return;
+ if (mWifiState != WifiManager.WIFI_STATE_ENABLED) return;
NetworkInfo.State state = networkInfo.getState();
if ((state == NetworkInfo.State.DISCONNECTED)
diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java
index 8ddc776..66ef978 100644
--- a/services/java/com/android/server/wifi/WifiService.java
+++ b/services/java/com/android/server/wifi/WifiService.java
@@ -651,7 +651,12 @@ public final class WifiService extends IWifiManager.Stub {
Slog.i(TAG, "WifiService trying to set country code to " + countryCode +
" with persist set to " + persist);
enforceChangePermission();
- mWifiStateMachine.setCountryCode(countryCode, persist);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mWifiStateMachine.setCountryCode(countryCode, persist);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
/**
@@ -668,7 +673,12 @@ public final class WifiService extends IWifiManager.Stub {
if (!isDualBandSupported()) return;
Slog.i(TAG, "WifiService trying to set frequency band to " + band +
" with persist set to " + persist);
- mWifiStateMachine.setFrequencyBand(band, persist);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mWifiStateMachine.setFrequencyBand(band, persist);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
diff --git a/services/jni/com_android_server_BatteryService.cpp b/services/jni/com_android_server_BatteryService.cpp
index 485c289..433950d 100644
--- a/services/jni/com_android_server_BatteryService.cpp
+++ b/services/jni/com_android_server_BatteryService.cpp
@@ -144,7 +144,7 @@ static jint getBatteryHealth(const char* status)
static int readFromFile(const String8& path, char* buf, size_t size)
{
- if (!path)
+ if (path.isEmpty())
return -1;
int fd = open(path.string(), O_RDONLY, 0);
if (fd == -1) {
diff --git a/services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java b/services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java
index 275d807..e2253a2 100644
--- a/services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java
@@ -17,10 +17,13 @@
package com.android.server;
import static com.android.server.NativeDaemonConnector.appendEscaped;
+import static com.android.server.NativeDaemonConnector.makeCommand;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.server.NativeDaemonConnector.SensitiveArg;
+
/**
* Tests for {@link NativeDaemonConnector}.
*/
@@ -67,4 +70,28 @@ public class NativeDaemonConnectorTest extends AndroidTestCase {
appendEscaped(builder, "caf\u00E9 c\u00F6ffee");
assertEquals("\"caf\u00E9 c\u00F6ffee\"", builder.toString());
}
+
+ public void testSensitiveArgs() throws Exception {
+ final StringBuilder rawBuilder = new StringBuilder();
+ final StringBuilder logBuilder = new StringBuilder();
+
+ rawBuilder.setLength(0);
+ logBuilder.setLength(0);
+ makeCommand(rawBuilder, logBuilder, 1, "foo", "bar", "baz");
+ assertEquals("1 foo bar baz\0", rawBuilder.toString());
+ assertEquals("1 foo bar baz", logBuilder.toString());
+
+ rawBuilder.setLength(0);
+ logBuilder.setLength(0);
+ makeCommand(rawBuilder, logBuilder, 1, "foo", new SensitiveArg("bar"), "baz");
+ assertEquals("1 foo bar baz\0", rawBuilder.toString());
+ assertEquals("1 foo [scrubbed] baz", logBuilder.toString());
+
+ rawBuilder.setLength(0);
+ logBuilder.setLength(0);
+ makeCommand(rawBuilder, logBuilder, 1, "foo", new SensitiveArg("foo bar"), "baz baz",
+ new SensitiveArg("wat"));
+ assertEquals("1 foo \"foo bar\" \"baz baz\" wat\0", rawBuilder.toString());
+ assertEquals("1 foo [scrubbed] \"baz baz\" [scrubbed]", logBuilder.toString());
+ }
}