summaryrefslogtreecommitdiffstats
path: root/services/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com')
-rw-r--r--services/java/com/android/server/LocationManagerService.java48
-rw-r--r--services/java/com/android/server/NetworkManagementService.java6
-rw-r--r--services/java/com/android/server/NotificationManagerService.java90
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java37
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java4
-rw-r--r--services/java/com/android/server/firewall/IntentFirewall.java146
-rw-r--r--services/java/com/android/server/location/GpsLocationProvider.java59
-rw-r--r--services/java/com/android/server/wm/WindowState.java2
8 files changed, 340 insertions, 52 deletions
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 1e1cf5a..b47e8a0 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -116,6 +116,8 @@ public class LocationManagerService extends ILocationManager.Stub {
private static final int MSG_LOCATION_CHANGED = 1;
+ private static final long NANOS_PER_MILLI = 1000000L;
+
// Location Providers may sometimes deliver location updates
// slightly faster that requested - provide grace period so
// we don't unnecessarily filter events that are otherwise on
@@ -179,6 +181,11 @@ public class LocationManagerService extends ILocationManager.Stub {
// mapping from provider name to last known location
private final HashMap<String, Location> mLastLocation = new HashMap<String, Location>();
+ // same as mLastLocation, but is not updated faster than LocationFudger.FASTEST_INTERVAL_MS.
+ // locations stored here are not fudged for coarse permissions.
+ private final HashMap<String, Location> mLastLocationCoarseInterval =
+ new HashMap<String, Location>();
+
// all providers that operate over proxy, for authorizing incoming location
private final ArrayList<LocationProviderProxy> mProxyProviders =
new ArrayList<LocationProviderProxy>();
@@ -423,6 +430,7 @@ public class LocationManagerService extends ILocationManager.Stub {
mLocationHandler.removeMessages(MSG_LOCATION_CHANGED);
synchronized (mLock) {
mLastLocation.clear();
+ mLastLocationCoarseInterval.clear();
for (LocationProviderInterface p : mProviders) {
updateProviderListenersLocked(p.getName(), false, mCurrentUserId);
}
@@ -1407,7 +1415,14 @@ public class LocationManagerService extends ILocationManager.Stub {
if (!isAllowedByUserSettingsLocked(name, uid)) return null;
- Location location = mLastLocation.get(name);
+ Location location;
+ if (allowedResolutionLevel < RESOLUTION_LEVEL_FINE) {
+ // Make sure that an app with coarse permissions can't get frequent location
+ // updates by calling LocationManager.getLastKnownLocation repeatedly.
+ location = mLastLocationCoarseInterval.get(name);
+ } else {
+ location = mLastLocation.get(name);
+ }
if (location == null) {
return null;
}
@@ -1673,7 +1688,8 @@ public class LocationManagerService extends ILocationManager.Stub {
// Check whether sufficient time has passed
long minTime = record.mRequest.getFastestInterval();
- long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos()) / 1000000L;
+ long delta = (loc.getElapsedRealtimeNanos() - lastLoc.getElapsedRealtimeNanos())
+ / NANOS_PER_MILLI;
if (delta < minTime - MAX_PROVIDER_SCHEDULING_JITTER_MS) {
return false;
}
@@ -1726,13 +1742,30 @@ public class LocationManagerService extends ILocationManager.Stub {
}
lastLocation.set(location);
+ // Update last known coarse interval location if enough time has passed.
+ Location lastLocationCoarseInterval = mLastLocationCoarseInterval.get(provider);
+ if (lastLocationCoarseInterval == null) {
+ lastLocationCoarseInterval = new Location(location);
+ mLastLocationCoarseInterval.put(provider, lastLocationCoarseInterval);
+ }
+ long timeDiffNanos = location.getElapsedRealtimeNanos()
+ - lastLocationCoarseInterval.getElapsedRealtimeNanos();
+ if (timeDiffNanos > LocationFudger.FASTEST_INTERVAL_MS * NANOS_PER_MILLI) {
+ lastLocationCoarseInterval.set(location);
+ }
+ // Don't ever return a coarse location that is more recent than the allowed update
+ // interval (i.e. don't allow an app to keep registering and unregistering for
+ // location updates to overcome the minimum interval).
+ noGPSLocation =
+ lastLocationCoarseInterval.getExtraLocation(Location.EXTRA_NO_GPS_LOCATION);
+
// Skip if there are no UpdateRecords for this provider.
ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
if (records == null || records.size() == 0) return;
// Fetch coarse location
Location coarseLocation = null;
- if (noGPSLocation != null && !noGPSLocation.equals(lastNoGPSLocation)) {
+ if (noGPSLocation != null) {
coarseLocation = mLocationFudger.getOrCreate(noGPSLocation);
}
@@ -2021,6 +2054,7 @@ public class LocationManagerService extends ILocationManager.Stub {
addProviderLocked(provider);
mMockProviders.put(name, provider);
mLastLocation.put(name, null);
+ mLastLocationCoarseInterval.put(name, null);
updateProvidersLocked();
}
Binder.restoreCallingIdentity(identity);
@@ -2043,6 +2077,7 @@ public class LocationManagerService extends ILocationManager.Stub {
addProviderLocked(realProvider);
}
mLastLocation.put(provider, null);
+ mLastLocationCoarseInterval.put(provider, null);
updateProvidersLocked();
Binder.restoreCallingIdentity(identity);
}
@@ -2174,6 +2209,13 @@ public class LocationManagerService extends ILocationManager.Stub {
pw.println(" " + provider + ": " + location);
}
+ pw.println(" Last Known Locations Coarse Intervals:");
+ for (Map.Entry<String, Location> entry : mLastLocationCoarseInterval.entrySet()) {
+ String provider = entry.getKey();
+ Location location = entry.getValue();
+ pw.println(" " + provider + ": " + location);
+ }
+
mGeofenceManager.dump(pw);
if (mEnabledProviders.size() > 0) {
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index d2acb40..0d266c2 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -990,7 +990,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
mConnector.execute("softap", "set", wlanIface);
} else {
mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
- getSecurityType(wifiConfig), wifiConfig.preSharedKey);
+ "broadcast", getSecurityType(wifiConfig),
+ wifiConfig.preSharedKey);
}
mConnector.execute("softap", "startap");
} catch (NativeDaemonConnectorException e) {
@@ -1039,7 +1040,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
mConnector.execute("softap", "set", wlanIface);
} else {
mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
- getSecurityType(wifiConfig), wifiConfig.preSharedKey);
+ "broadcast", getSecurityType(wifiConfig),
+ 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 cfb892f..fa18e76 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -43,11 +43,13 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.IAudioService;
import android.media.IRingtonePlayer;
import android.net.Uri;
import android.os.Binder;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
@@ -81,6 +83,7 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.reflect.Array;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
@@ -264,18 +267,32 @@ public class NotificationManagerService extends INotificationManager.Stub
}
private static class Archive {
- static final int BUFFER_SIZE = 1000;
+ static final int BUFFER_SIZE = 250;
ArrayDeque<StatusBarNotification> mBuffer = new ArrayDeque<StatusBarNotification>(BUFFER_SIZE);
public Archive() {
}
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ final int N = mBuffer.size();
+ sb.append("Archive (");
+ sb.append(N);
+ sb.append(" notification");
+ sb.append((N==1)?")":"s)");
+ return sb.toString();
+ }
+
public void record(StatusBarNotification nr) {
// Nuke heavy parts of notification before storing in archive
nr.notification.tickerView = null;
nr.notification.contentView = null;
nr.notification.bigContentView = null;
nr.notification.largeIcon = null;
+ final Bundle extras = nr.notification.extras;
+ extras.remove(Notification.EXTRA_LARGE_ICON);
+ extras.remove(Notification.EXTRA_LARGE_ICON_BIG);
+ extras.remove(Notification.EXTRA_PICTURE);
if (mBuffer.size() == BUFFER_SIZE) {
mBuffer.removeFirst();
@@ -283,6 +300,7 @@ public class NotificationManagerService extends INotificationManager.Stub
mBuffer.addLast(nr);
}
+
public void clear() {
mBuffer.clear();
}
@@ -815,22 +833,61 @@ public class NotificationManagerService extends INotificationManager.Stub
void dump(PrintWriter pw, String prefix, Context baseContext) {
final Notification notification = sbn.notification;
pw.println(prefix + this);
+ pw.println(prefix + " uid=" + sbn.uid + " userId=" + sbn.getUserId());
pw.println(prefix + " icon=0x" + Integer.toHexString(notification.icon)
- + " / " + idDebugString(baseContext, this.sbn.pkg, notification.icon));
- pw.println(prefix + " pri=" + notification.priority);
- pw.println(prefix + " score=" + this.sbn.score);
+ + " / " + idDebugString(baseContext, sbn.pkg, notification.icon));
+ pw.println(prefix + " pri=" + notification.priority + " score=" + sbn.score);
pw.println(prefix + " contentIntent=" + notification.contentIntent);
pw.println(prefix + " deleteIntent=" + notification.deleteIntent);
pw.println(prefix + " tickerText=" + notification.tickerText);
pw.println(prefix + " contentView=" + notification.contentView);
- pw.println(prefix + " uid=" + this.sbn.uid + " userId=" + this.sbn.getUserId());
- pw.println(prefix + " defaults=0x" + Integer.toHexString(notification.defaults));
- pw.println(prefix + " flags=0x" + Integer.toHexString(notification.flags));
+ pw.println(prefix + String.format(" defaults=0x%08x flags=0x%08x",
+ notification.defaults, notification.flags));
pw.println(prefix + " sound=" + notification.sound);
pw.println(prefix + " vibrate=" + Arrays.toString(notification.vibrate));
- pw.println(prefix + " ledARGB=0x" + Integer.toHexString(notification.ledARGB)
- + " ledOnMS=" + notification.ledOnMS
- + " ledOffMS=" + notification.ledOffMS);
+ pw.println(prefix + String.format(" led=0x%08x onMs=%d offMs=%d",
+ notification.ledARGB, notification.ledOnMS, notification.ledOffMS));
+ if (notification.actions != null && notification.actions.length > 0) {
+ pw.println(prefix + " actions={");
+ final int N = notification.actions.length;
+ for (int i=0; i<N; i++) {
+ final Notification.Action action = notification.actions[i];
+ pw.println(String.format("%s [%d] \"%s\" -> %s",
+ prefix,
+ i,
+ action.title,
+ action.actionIntent.toString()
+ ));
+ }
+ pw.println(prefix + " }");
+ }
+ if (notification.extras != null && notification.extras.size() > 0) {
+ pw.println(prefix + " extras={");
+ for (String key : notification.extras.keySet()) {
+ pw.print(prefix + " " + key + "=");
+ Object val = notification.extras.get(key);
+ if (val == null) {
+ pw.println("null");
+ } else {
+ pw.print(val.toString());
+ if (val instanceof Bitmap) {
+ pw.print(String.format(" (%dx%d)",
+ ((Bitmap) val).getWidth(),
+ ((Bitmap) val).getHeight()));
+ } else if (val.getClass().isArray()) {
+ pw.println(" {");
+ final int N = Array.getLength(val);
+ for (int i=0; i<N; i++) {
+ if (i > 0) pw.println(",");
+ pw.print(prefix + " " + Array.get(val, i));
+ }
+ pw.print("\n" + prefix + " }");
+ }
+ pw.println();
+ }
+ }
+ pw.println(prefix + " }");
+ }
}
@Override
@@ -2081,7 +2138,7 @@ public class NotificationManagerService extends INotificationManager.Stub
if (N > 0) {
pw.println(" Lights List:");
for (int i=0; i<N; i++) {
- mLights.get(i).dump(pw, " ", mContext);
+ pw.println(" " + mLights.get(i));
}
pw.println(" ");
}
@@ -2090,6 +2147,17 @@ public class NotificationManagerService extends INotificationManager.Stub
pw.println(" mVibrateNotification=" + mVibrateNotification);
pw.println(" mDisabledNotifications=0x" + Integer.toHexString(mDisabledNotifications));
pw.println(" mSystemReady=" + mSystemReady);
+ pw.println(" mArchive=" + mArchive.toString());
+ Iterator<StatusBarNotification> iter = mArchive.descendingIterator();
+ int i=0;
+ while (iter.hasNext()) {
+ pw.println(" " + iter.next());
+ if (++i >= 5) {
+ if (iter.hasNext()) pw.println(" ...");
+ break;
+ }
+ }
+
}
}
}
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 110c4da..1f3ac96 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -970,7 +970,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private void addServiceLocked(Service service, UserState userState) {
try {
- service.linkToOwnDeath();
+ service.linkToOwnDeathLocked();
userState.mBoundServices.add(service);
userState.mComponentNameToServiceMap.put(service.mComponentName, service);
} catch (RemoteException re) {
@@ -987,7 +987,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
private void removeServiceLocked(Service service, UserState userState) {
userState.mBoundServices.remove(service);
userState.mComponentNameToServiceMap.remove(service.mComponentName);
- service.unlinkToOwnDeath();
+ service.unlinkToOwnDeathLocked();
}
/**
@@ -1765,7 +1765,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
userState.destroyUiAutomationService();
}
removeServiceLocked(this, userState);
- dispose();
+ resetLocked();
return true;
}
@@ -1817,11 +1817,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
addServiceLocked(this, userState);
if (userState.mBindingServices.contains(mComponentName)) {
userState.mBindingServices.remove(mComponentName);
- onUserStateChangedLocked(userState);
try {
- mServiceInterface.setConnection(this, mId);
+ mServiceInterface.setConnection(this, mId);
+ onUserStateChangedLocked(userState);
} catch (RemoteException re) {
- Slog.w(LOG_TAG, "Error while setting connection for service: " + service, re);
+ Slog.w(LOG_TAG, "Error while setting connection for service: "
+ + service, re);
+ binderDied();
}
} else {
binderDied();
@@ -2148,15 +2150,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
/* do nothing - #binderDied takes care */
}
- public void linkToOwnDeath() throws RemoteException {
+ public void linkToOwnDeathLocked() throws RemoteException {
mService.linkToDeath(this, 0);
}
- public void unlinkToOwnDeath() {
+ public void unlinkToOwnDeathLocked() {
mService.unlinkToDeath(this, 0);
}
- public void dispose() {
+ public void resetLocked() {
try {
// Clear the proxy in the other process so this
// IAccessibilityServiceConnection can be garbage collected.
@@ -2168,13 +2170,24 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
mServiceInterface = null;
}
+ public boolean isInitializedLocked() {
+ return (mService != null);
+ }
+
public void binderDied() {
synchronized (mLock) {
+ // It is possible that this service's package was force stopped during
+ // whose handling the death recipient is unlinked and still get a call
+ // on binderDied since the call was made before we unlink but was
+ // waiting on the lock we held during the force stop handling.
+ if (!isInitializedLocked()) {
+ return;
+ }
mKeyEventDispatcher.flush();
UserState userState = getUserStateLocked(mUserId);
// The death recipient is unregistered in removeServiceLocked
removeServiceLocked(this, userState);
- dispose();
+ resetLocked();
if (mIsAutomation) {
// We no longer have an automation service, so restore
// the state based on values in the settings database.
@@ -2499,7 +2512,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
public void flush() {
synchronized (mLock) {
cancelAllPendingEventsLocked();
- mSentEventsVerifier.reset();
+ if (mSentEventsVerifier != null) {
+ mSentEventsVerifier.reset();
+ }
}
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 16c7824..a3bb823 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -5024,6 +5024,10 @@ public final class ActivityManagerService extends ActivityManagerNative
return ActivityManagerService.this.checkComponentPermission(permission, pid, uid,
owningUid, exported);
}
+
+ public Object getAMSLock() {
+ return ActivityManagerService.this;
+ }
}
/**
diff --git a/services/java/com/android/server/firewall/IntentFirewall.java b/services/java/com/android/server/firewall/IntentFirewall.java
index 08e6b45..edba243 100644
--- a/services/java/com/android/server/firewall/IntentFirewall.java
+++ b/services/java/com/android/server/firewall/IntentFirewall.java
@@ -25,6 +25,9 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.os.Environment;
+import android.os.FileObserver;
+import android.os.Handler;
+import android.os.Message;
import android.os.RemoteException;
import android.util.Slog;
import android.util.Xml;
@@ -58,19 +61,18 @@ public class IntentFirewall {
private static final String TAG_BROADCAST = "broadcast";
private static final int TYPE_ACTIVITY = 0;
- private static final int TYPE_SERVICE = 1;
- private static final int TYPE_BROADCAST = 2;
+ private static final int TYPE_BROADCAST = 1;
+ private static final int TYPE_SERVICE = 2;
private static final HashMap<String, FilterFactory> factoryMap;
private final AMSInterface mAms;
- private final IntentResolver<FirewallIntentFilter, Rule> mActivityResolver =
- new FirewallIntentResolver();
- private final IntentResolver<FirewallIntentFilter, Rule> mServiceResolver =
- new FirewallIntentResolver();
- private final IntentResolver<FirewallIntentFilter, Rule> mBroadcastResolver =
- new FirewallIntentResolver();
+ private final RuleObserver mObserver;
+
+ private FirewallIntentResolver mActivityResolver = new FirewallIntentResolver();
+ private FirewallIntentResolver mBroadcastResolver = new FirewallIntentResolver();
+ private FirewallIntentResolver mServiceResolver = new FirewallIntentResolver();
static {
FilterFactory[] factories = new FilterFactory[] {
@@ -104,9 +106,18 @@ public class IntentFirewall {
public IntentFirewall(AMSInterface ams) {
mAms = ams;
- readRules(getRulesFile());
+ File rulesFile = getRulesFile();
+
+ readRules(rulesFile);
+
+ mObserver = new RuleObserver(rulesFile);
+ mObserver.startWatching();
}
+ /**
+ * This is called from ActivityManager to check if a start activity intent should be allowed.
+ * It is assumed the caller is already holding the global ActivityManagerService lock.
+ */
public boolean checkStartActivity(Intent intent, ApplicationInfo callerApp, int callerUid,
int callerPid, String resolvedType, ActivityInfo resolvedActivity) {
List<Rule> matchingRules = mActivityResolver.queryIntent(intent, resolvedType, false, 0);
@@ -208,7 +219,18 @@ public class IntentFirewall {
return RULES_FILE;
}
+ /**
+ * Reads rules from the given file and replaces our set of rules with the newly read rules
+ *
+ * All calls to this method from the file observer come through a handler and are inherently
+ * serialized
+ */
private void readRules(File rulesFile) {
+ FirewallIntentResolver[] resolvers = new FirewallIntentResolver[3];
+ for (int i=0; i<resolvers.length; i++) {
+ resolvers[i] = new FirewallIntentResolver();
+ }
+
FileInputStream fis;
try {
fis = new FileInputStream(rulesFile);
@@ -224,40 +246,59 @@ public class IntentFirewall {
XmlUtils.beginDocument(parser, TAG_RULES);
+ int[] numRules = new int[3];
+
int outerDepth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
- IntentResolver<FirewallIntentFilter, Rule> resolver = null;
+ int ruleType = -1;
+
String tagName = parser.getName();
if (tagName.equals(TAG_ACTIVITY)) {
- resolver = mActivityResolver;
- } else if (tagName.equals(TAG_SERVICE)) {
- resolver = mServiceResolver;
+ ruleType = TYPE_ACTIVITY;
} else if (tagName.equals(TAG_BROADCAST)) {
- resolver = mBroadcastResolver;
+ ruleType = TYPE_BROADCAST;
+ } else if (tagName.equals(TAG_SERVICE)) {
+ ruleType = TYPE_SERVICE;
}
- if (resolver != null) {
+ if (ruleType != -1) {
Rule rule = new Rule();
+ FirewallIntentResolver resolver = resolvers[ruleType];
+
+ // if we get an error while parsing a particular rule, we'll just ignore
+ // that rule and continue on with the next rule
try {
rule.readFromXml(parser);
} catch (XmlPullParserException ex) {
Slog.e(TAG, "Error reading intent firewall rule", ex);
continue;
- } catch (IOException ex) {
- Slog.e(TAG, "Error reading intent firewall rule", ex);
- continue;
}
+ numRules[ruleType]++;
+
for (int i=0; i<rule.getIntentFilterCount(); i++) {
resolver.addFilter(rule.getIntentFilter(i));
}
}
}
+
+ Slog.i(TAG, "Read new rules (A:" + numRules[TYPE_ACTIVITY] +
+ " B:" + numRules[TYPE_BROADCAST] + " S:" + numRules[TYPE_SERVICE] + ")");
+
+ synchronized (mAms.getAMSLock()) {
+ mActivityResolver = resolvers[TYPE_ACTIVITY];
+ mBroadcastResolver = resolvers[TYPE_BROADCAST];
+ mServiceResolver = resolvers[TYPE_SERVICE];
+ }
} catch (XmlPullParserException ex) {
+ // if there was an error outside of a specific rule, then there are probably
+ // structural problems with the xml file, and we should completely ignore it
Slog.e(TAG, "Error reading intent firewall rules", ex);
+ clearRules();
} catch (IOException ex) {
Slog.e(TAG, "Error reading intent firewall rules", ex);
+ clearRules();
} finally {
try {
fis.close();
@@ -267,6 +308,22 @@ public class IntentFirewall {
}
}
+ /**
+ * Clears out all of our rules
+ *
+ * All calls to this method from the file observer come through a handler and are inherently
+ * serialized
+ */
+ private void clearRules() {
+ Slog.i(TAG, "Clearing all rules");
+
+ synchronized (mAms.getAMSLock()) {
+ mActivityResolver = new FirewallIntentResolver();
+ mBroadcastResolver = new FirewallIntentResolver();
+ mServiceResolver = new FirewallIntentResolver();
+ }
+ }
+
static Filter parseFilter(XmlPullParser parser) throws IOException, XmlPullParserException {
String elementName = parser.getName();
@@ -363,6 +420,58 @@ public class IntentFirewall {
}
}
+ private static final int READ_RULES = 0;
+ private static final int CLEAR_RULES = 1;
+
+ final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case READ_RULES:
+ readRules(getRulesFile());
+ break;
+ case CLEAR_RULES:
+ clearRules();
+ break;
+ }
+ }
+ };
+
+ /**
+ * Monitors for the creation/deletion/modification of the rule file
+ */
+ private class RuleObserver extends FileObserver {
+ // The file name we're monitoring, with no path component
+ private final String mMonitoredFile;
+
+ private static final int CREATED_FLAGS = FileObserver.CREATE|FileObserver.MOVED_TO|
+ FileObserver.CLOSE_WRITE;
+ private static final int DELETED_FLAGS = FileObserver.DELETE|FileObserver.MOVED_FROM;
+
+ public RuleObserver(File monitoredFile) {
+ super(monitoredFile.getParentFile().getAbsolutePath(), CREATED_FLAGS|DELETED_FLAGS);
+ mMonitoredFile = monitoredFile.getName();
+ }
+
+ @Override
+ public void onEvent(int event, String path) {
+ if (path.equals(mMonitoredFile)) {
+ // we wait 250ms before taking any action on an event, in order to dedup multiple
+ // events. E.g. a delete event followed by a create event followed by a subsequent
+ // write+close event;
+ if ((event & CREATED_FLAGS) != 0) {
+ mHandler.removeMessages(READ_RULES);
+ mHandler.removeMessages(CLEAR_RULES);
+ mHandler.sendEmptyMessageDelayed(READ_RULES, 250);
+ } else if ((event & DELETED_FLAGS) != 0) {
+ mHandler.removeMessages(READ_RULES);
+ mHandler.removeMessages(CLEAR_RULES);
+ mHandler.sendEmptyMessageDelayed(CLEAR_RULES, 250);
+ }
+ }
+ }
+ }
+
/**
* This interface contains the methods we need from ActivityManagerService. This allows AMS to
* export these methods to us without making them public, and also makes it easier to test this
@@ -371,6 +480,7 @@ public class IntentFirewall {
public interface AMSInterface {
int checkComponentPermission(String permission, int pid, int uid,
int owningUid, boolean exported);
+ Object getAMSLock();
}
/**
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 1ebff67..8c88cab 100644
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -36,6 +36,7 @@ import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
+import android.location.LocationRequest;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
@@ -262,6 +263,9 @@ public class GpsLocationProvider implements LocationProviderInterface {
// true if we started navigation
private boolean mStarted;
+ // true if single shot request is in progress
+ private boolean mSingleShot;
+
// capabilities of the GPS engine
private int mEngineCapabilities;
@@ -382,7 +386,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
if (action.equals(ALARM_WAKEUP)) {
if (DEBUG) Log.d(TAG, "ALARM_WAKEUP");
- startNavigating();
+ startNavigating(false);
} else if (action.equals(ALARM_TIMEOUT)) {
if (DEBUG) Log.d(TAG, "ALARM_TIMEOUT");
hibernate();
@@ -803,10 +807,22 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
private void handleSetRequest(ProviderRequest request, WorkSource source) {
- if (DEBUG) Log.d(TAG, "setRequest " + request);
+ boolean singleShot = false;
+ // see if the request is for a single update
+ if (request.locationRequests != null && request.locationRequests.size() > 0) {
+ // if any request has zero or more than one updates
+ // requested, then this is not single-shot mode
+ singleShot = true;
+ for (LocationRequest lr : request.locationRequests) {
+ if (lr.getNumUpdates() != 1) {
+ singleShot = false;
+ }
+ }
+ }
+ if (DEBUG) Log.d(TAG, "setRequest " + request);
if (request.reportLocation) {
// update client uids
updateClientUids(source);
@@ -828,7 +844,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
} else if (!mStarted) {
// start GPS
- startNavigating();
+ startNavigating(singleShot);
}
} else {
updateClientUids(new WorkSource());
@@ -982,21 +998,44 @@ public class GpsLocationProvider implements LocationProviderInterface {
return false;
}
- private void startNavigating() {
+ private void startNavigating(boolean singleShot) {
if (!mStarted) {
- if (DEBUG) Log.d(TAG, "startNavigating");
+ if (DEBUG) Log.d(TAG, "startNavigating, singleShot is " + singleShot);
mTimeToFirstFix = 0;
mLastFixTime = 0;
mStarted = true;
+ mSingleShot = singleShot;
mPositionMode = GPS_POSITION_MODE_STANDALONE;
if (Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.ASSISTED_GPS_ENABLED, 1) != 0) {
- if (hasCapability(GPS_CAPABILITY_MSB)) {
+ if (singleShot && hasCapability(GPS_CAPABILITY_MSA)) {
+ mPositionMode = GPS_POSITION_MODE_MS_ASSISTED;
+ } else if (hasCapability(GPS_CAPABILITY_MSB)) {
mPositionMode = GPS_POSITION_MODE_MS_BASED;
}
}
+ if (DEBUG) {
+ String mode;
+
+ switch(mPositionMode) {
+ case GPS_POSITION_MODE_STANDALONE:
+ mode = "standalone";
+ break;
+ case GPS_POSITION_MODE_MS_ASSISTED:
+ mode = "MS_ASSISTED";
+ break;
+ case GPS_POSITION_MODE_MS_BASED:
+ mode = "MS_BASED";
+ break;
+ default:
+ mode = "unknown";
+ break;
+ }
+ Log.d(TAG, "setting position_mode to " + mode);
+ }
+
int interval = (hasCapability(GPS_CAPABILITY_SCHEDULING) ? mFixInterval : 1000);
if (!native_set_position_mode(mPositionMode, GPS_POSITION_RECURRENCE_PERIODIC,
interval, 0, 0)) {
@@ -1028,6 +1067,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
if (DEBUG) Log.d(TAG, "stopNavigating");
if (mStarted) {
mStarted = false;
+ mSingleShot = false;
native_stop();
mTimeToFirstFix = 0;
mLastFixTime = 0;
@@ -1122,6 +1162,10 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
}
+ if (mSingleShot) {
+ stopNavigating();
+ }
+
if (mStarted && mStatus != LocationProvider.AVAILABLE) {
// we want to time out if we do not receive a fix
// within the time out and we are requesting infrequent fixes
@@ -1283,7 +1327,8 @@ public class GpsLocationProvider implements LocationProviderInterface {
if (DEBUG) Log.d(TAG, "PhoneConstants.APN_REQUEST_STARTED");
// Nothing to do here
} else {
- if (DEBUG) Log.d(TAG, "startUsingNetworkFeature failed");
+ if (DEBUG) Log.d(TAG, "startUsingNetworkFeature failed, value is " +
+ result);
mAGpsDataConnectionState = AGPS_DATA_CONNECTION_CLOSED;
native_agps_data_conn_failed();
}
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index d4c727b..905f55d 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
@@ -948,6 +949,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return mContentChanged && !mExiting && !mWinAnimator.mLastHidden && mService.okToDisplay()
&& (mFrame.top != mLastFrame.top
|| mFrame.left != mLastFrame.left)
+ && (mAttrs.privateFlags&PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
&& (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove());
}