diff options
Diffstat (limited to 'services/java/com')
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()); } |