diff options
Diffstat (limited to 'services/java/com')
19 files changed, 610 insertions, 218 deletions
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 0843948..9a9cc8f 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -1995,7 +1995,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { } } else { try { - mNetd.setDnsServersForInterface(Integer.toString(netType), + mNetd.setDnsServersForInterface(p.getInterfaceName(), NetworkUtils.makeStrings(dnses)); } catch (Exception e) { Slog.e(TAG, "exception setting dns servers: " + e); diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index 17ad268..39d2b1c 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -125,10 +125,14 @@ class NetworkManagementService extends INetworkManagementService.Stub { private Thread mThread; private final CountDownLatch mConnectedSignal = new CountDownLatch(1); + // TODO: replace with RemoteCallbackList private ArrayList<INetworkManagementEventObserver> mObservers; + private Object mQuotaLock = new Object(); /** Set of interfaces with active quotas. */ - private HashSet<String> mInterfaceQuota = Sets.newHashSet(); + private HashSet<String> mActiveQuotaIfaces = Sets.newHashSet(); + /** Set of interfaces with active alerts. */ + private HashSet<String> mActiveAlertIfaces = Sets.newHashSet(); /** Set of UIDs with active reject rules. */ private SparseBooleanArray mUidRejectOnQuota = new SparseBooleanArray(); @@ -1058,26 +1062,25 @@ class NetworkManagementService extends INetworkManagementService.Stub { } @Override - public void setInterfaceQuota(String iface, long quota) { + public void setInterfaceQuota(String iface, long quotaBytes) { mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); // silently discard when control disabled // TODO: eventually migrate to be always enabled if (!mBandwidthControlEnabled) return; - synchronized (mInterfaceQuota) { - if (mInterfaceQuota.contains(iface)) { - // TODO: eventually consider throwing - return; + synchronized (mQuotaLock) { + if (mActiveQuotaIfaces.contains(iface)) { + throw new IllegalStateException("iface " + iface + " already has quota"); } final StringBuilder command = new StringBuilder(); - command.append("bandwidth setiquota ").append(iface).append(" ").append(quota); + command.append("bandwidth setiquota ").append(iface).append(" ").append(quotaBytes); try { - // TODO: add support for quota shared across interfaces + // TODO: support quota shared across interfaces mConnector.doCommand(command.toString()); - mInterfaceQuota.add(iface); + mActiveQuotaIfaces.add(iface); } catch (NativeDaemonConnectorException e) { throw new IllegalStateException("Error communicating to native daemon", e); } @@ -1092,8 +1095,8 @@ class NetworkManagementService extends INetworkManagementService.Stub { // TODO: eventually migrate to be always enabled if (!mBandwidthControlEnabled) return; - synchronized (mInterfaceQuota) { - if (!mInterfaceQuota.contains(iface)) { + synchronized (mQuotaLock) { + if (!mActiveQuotaIfaces.contains(iface)) { // TODO: eventually consider throwing return; } @@ -1102,9 +1105,42 @@ class NetworkManagementService extends INetworkManagementService.Stub { command.append("bandwidth removeiquota ").append(iface); try { - // TODO: add support for quota shared across interfaces + // TODO: support quota shared across interfaces + mConnector.doCommand(command.toString()); + mActiveQuotaIfaces.remove(iface); + mActiveAlertIfaces.remove(iface); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException("Error communicating to native daemon", e); + } + } + } + + @Override + public void setInterfaceAlert(String iface, long alertBytes) { + mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); + + // silently discard when control disabled + // TODO: eventually migrate to be always enabled + if (!mBandwidthControlEnabled) return; + + // quick sanity check + if (!mActiveQuotaIfaces.contains(iface)) { + throw new IllegalStateException("setting alert requires existing quota on iface"); + } + + synchronized (mQuotaLock) { + if (mActiveAlertIfaces.contains(iface)) { + throw new IllegalStateException("iface " + iface + " already has alert"); + } + + final StringBuilder command = new StringBuilder(); + command.append("bandwidth setinterfacealert ").append(iface).append(" ").append( + alertBytes); + + try { + // TODO: support alert shared across interfaces mConnector.doCommand(command.toString()); - mInterfaceQuota.remove(iface); + mActiveAlertIfaces.add(iface); } catch (NativeDaemonConnectorException e) { throw new IllegalStateException("Error communicating to native daemon", e); } @@ -1112,6 +1148,51 @@ class NetworkManagementService extends INetworkManagementService.Stub { } @Override + public void removeInterfaceAlert(String iface) { + mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); + + // silently discard when control disabled + // TODO: eventually migrate to be always enabled + if (!mBandwidthControlEnabled) return; + + synchronized (mQuotaLock) { + if (!mActiveAlertIfaces.contains(iface)) { + // TODO: eventually consider throwing + return; + } + + final StringBuilder command = new StringBuilder(); + command.append("bandwidth removeinterfacealert ").append(iface); + + try { + // TODO: support alert shared across interfaces + mConnector.doCommand(command.toString()); + mActiveAlertIfaces.remove(iface); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException("Error communicating to native daemon", e); + } + } + } + + @Override + public void setGlobalAlert(long alertBytes) { + mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); + + // silently discard when control disabled + // TODO: eventually migrate to be always enabled + if (!mBandwidthControlEnabled) return; + + final StringBuilder command = new StringBuilder(); + command.append("bandwidth setglobalalert ").append(alertBytes); + + try { + mConnector.doCommand(command.toString()); + } catch (NativeDaemonConnectorException e) { + throw new IllegalStateException("Error communicating to native daemon", e); + } + } + + @Override public void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); @@ -1375,18 +1456,17 @@ class NetworkManagementService extends INetworkManagementService.Stub { try { String cmd = "resolver setifdns " + iface; for (String s : servers) { - if (s != null && !"0.0.0.0".equals(s) && - !"::".equals(s) && !"0:0:0:0:0:0:0:0".equals(s)) { - cmd += " " + InetAddress.getByName(s).getHostAddress(); + InetAddress a = NetworkUtils.numericToInetAddress(s); + if (a.isAnyLocalAddress() == false) { + cmd += " " + a.getHostAddress(); } } - mConnector.doCommand(cmd); - } catch (UnknownHostException e) { - throw new IllegalStateException("failed to resolve dns address.", e); + } catch (IllegalArgumentException e) { + throw new IllegalStateException("Error setting dnsn for interface", e); } catch (NativeDaemonConnectorException e) { throw new IllegalStateException( - "Error communicating with native deamon to set dns for interface", e); + "Error communicating with native daemon to set dns for interface", e); } } @@ -1412,7 +1492,7 @@ class NetworkManagementService extends INetworkManagementService.Stub { mConnector.doCommand(cmd); } catch (NativeDaemonConnectorException e) { throw new IllegalStateException( - "Error communicating with native deamon to flush interface " + iface, e); + "Error communicating with native daemon to flush interface " + iface, e); } } } diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java index 92647e6..d0f8843 100644 --- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -1205,6 +1205,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED | AccessibilityEvent.TYPE_VIEW_SCROLLED; + private static final int RETRIEVAL_ALLOWING_WINDOW_CHANGE_EVENT_TYPES = + AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER + | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT; + private int mRetrievalAlowingWindowId; private boolean canDispatchAccessibilityEvent(AccessibilityEvent event) { @@ -1216,9 +1220,10 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub public void updateRetrievalAllowingWindowAndEventSourceLocked(AccessibilityEvent event) { final int windowId = event.getWindowId(); final int eventType = event.getEventType(); - if ((eventType & RETRIEVAL_ALLOWING_EVENT_TYPES) != 0) { + if ((eventType & RETRIEVAL_ALLOWING_WINDOW_CHANGE_EVENT_TYPES) != 0) { mRetrievalAlowingWindowId = windowId; - } else { + } + if ((eventType & RETRIEVAL_ALLOWING_EVENT_TYPES) == 0) { event.setSource(null); } } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 3389f33..66f88fc 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -1821,7 +1821,7 @@ public final class ActivityManagerService extends ActivityManagerNative // An application record is attached to a previous process, // clean it up now. if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app); - handleAppDiedLocked(app, true); + handleAppDiedLocked(app, true, true); } } @@ -2658,8 +2658,8 @@ public final class ActivityManagerService extends ActivityManagerNative * to the process. */ private final void handleAppDiedLocked(ProcessRecord app, - boolean restarting) { - cleanUpApplicationRecordLocked(app, restarting, -1); + boolean restarting, boolean allowRestart) { + cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1); if (!restarting) { mLruProcesses.remove(app); } @@ -2791,7 +2791,7 @@ public final class ActivityManagerService extends ActivityManagerNative TAG, "Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder()); boolean doLowMem = app.instrumentationClass == null; - handleAppDiedLocked(app, false); + handleAppDiedLocked(app, false, true); if (doLowMem) { // If there are no longer any background processes running, @@ -3195,7 +3195,7 @@ public final class ActivityManagerService extends ActivityManagerNative return; } killPackageProcessesLocked(packageName, pkgUid, - SECONDARY_SERVER_ADJ, false, true); + SECONDARY_SERVER_ADJ, false, true, true); } } finally { Binder.restoreCallingIdentity(callingId); @@ -3358,7 +3358,7 @@ public final class ActivityManagerService extends ActivityManagerNative } private final boolean killPackageProcessesLocked(String packageName, int uid, - int minOomAdj, boolean callerWillRestart, boolean doit) { + int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit) { ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(); // Remove all processes this package may have touched: all with the @@ -3369,6 +3369,10 @@ public final class ActivityManagerService extends ActivityManagerNative final int NA = apps.size(); for (int ia=0; ia<NA; ia++) { ProcessRecord app = apps.valueAt(ia); + if (app.persistent) { + // we don't kill persistent processes + continue; + } if (app.removed) { if (doit) { procs.add(app); @@ -3389,7 +3393,7 @@ public final class ActivityManagerService extends ActivityManagerNative int N = procs.size(); for (int i=0; i<N; i++) { - removeProcessLocked(procs.get(i), callerWillRestart); + removeProcessLocked(procs.get(i), callerWillRestart, allowRestart); } return N > 0; } @@ -3419,11 +3423,12 @@ public final class ActivityManagerService extends ActivityManagerNative } boolean didSomething = killPackageProcessesLocked(name, uid, -100, - callerWillRestart, doit); + callerWillRestart, false, doit); for (i=mMainStack.mHistory.size()-1; i>=0; i--) { ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i); - if (r.packageName.equals(name)) { + if (r.packageName.equals(name) + && (r.app == null || !r.app.persistent)) { if (!doit) { return true; } @@ -3439,7 +3444,8 @@ public final class ActivityManagerService extends ActivityManagerNative ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>(); for (ServiceRecord service : mServices.values()) { - if (service.packageName.equals(name)) { + if (service.packageName.equals(name) + && (service.app == null || !service.app.persistent)) { if (!doit) { return true; } @@ -3471,7 +3477,8 @@ public final class ActivityManagerService extends ActivityManagerNative return didSomething; } - private final boolean removeProcessLocked(ProcessRecord app, boolean callerWillRestart) { + private final boolean removeProcessLocked(ProcessRecord app, + boolean callerWillRestart, boolean allowRestart) { final String name = app.processName; final int uid = app.info.uid; if (DEBUG_PROCESSES) Slog.d( @@ -3490,7 +3497,7 @@ public final class ActivityManagerService extends ActivityManagerNative mPidsSelfLocked.remove(pid); mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); } - handleAppDiedLocked(app, true); + handleAppDiedLocked(app, true, allowRestart); mLruProcesses.remove(app); Process.killProcess(pid); @@ -3600,7 +3607,7 @@ public final class ActivityManagerService extends ActivityManagerNative // If this application record is still attached to a previous // process, clean it up now. if (app.thread != null) { - handleAppDiedLocked(app, true); + handleAppDiedLocked(app, true, true); } // Tell the process all about itself. @@ -3783,7 +3790,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (badApp) { // todo: Also need to kill application to deal with all // kinds of exceptions. - handleAppDiedLocked(app, false); + handleAppDiedLocked(app, false, true); return false; } @@ -6643,7 +6650,7 @@ public final class ActivityManagerService extends ActivityManagerNative for (int i=procsToKill.size()-1; i>=0; i--) { ProcessRecord proc = procsToKill.get(i); Slog.i(TAG, "Removing system update proc: " + proc); - removeProcessLocked(proc, true); + removeProcessLocked(proc, true, false); } } @@ -6826,10 +6833,6 @@ public final class ActivityManagerService extends ActivityManagerNative } } if (!app.persistent) { - // Don't let services in this process be restarted and potentially - // annoy the user repeatedly. Unless it is persistent, since those - // processes run critical code. - killServicesLocked(app, false); // We don't want to start this process again until the user // explicitly does so... but for persistent process, we really // need to keep it running. If a persistent process is actually @@ -6840,7 +6843,10 @@ public final class ActivityManagerService extends ActivityManagerNative app.bad = true; mProcessCrashTimes.remove(app.info.processName, app.info.uid); app.removed = true; - removeProcessLocked(app, false); + // Don't let services in this process be restarted and potentially + // annoy the user repeatedly. Unless it is persistent, since those + // processes run critical code. + removeProcessLocked(app, false, false); mMainStack.resumeTopActivityLocked(null); return false; } @@ -9120,7 +9126,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Should the service remain running? Note that in the // extreme case of so many attempts to deliver a command - // that it failed, that we also will stop it here. + // that it failed we also will stop it here. if (sr.startRequested && (sr.stopIfKilled || canceled)) { if (sr.pendingStarts.size() == 0) { sr.startRequested = false; @@ -9189,7 +9195,7 @@ public final class ActivityManagerService extends ActivityManagerNative * a process when running in single process mode. */ private final void cleanUpApplicationRecordLocked(ProcessRecord app, - boolean restarting, int index) { + boolean restarting, boolean allowRestart, int index) { if (index >= 0) { mLruProcesses.remove(index); } @@ -9221,7 +9227,7 @@ public final class ActivityManagerService extends ActivityManagerNative app.foregroundActivities = false; app.hasShownUi = false; - killServicesLocked(app, true); + killServicesLocked(app, allowRestart); boolean restart = false; @@ -9238,7 +9244,7 @@ public final class ActivityManagerService extends ActivityManagerNative // See if someone is waiting for this provider... in which // case we don't remove it, but just let it restart. int i = 0; - if (!app.bad) { + if (!app.bad && allowRestart) { for (; i<NL; i++) { if (mLaunchingProviders.get(i) == cpr) { restart = true; @@ -9994,8 +10000,12 @@ public final class ActivityManagerService extends ActivityManagerNative while (it.hasNext()) { ArrayList<ConnectionRecord> c = it.next(); for (int i=0; i<c.size(); i++) { + ConnectionRecord cr = c.get(i); + // There is still a connection to the service that is + // being brought down. Mark it as dead. + cr.serviceDead = true; try { - c.get(i).conn.connected(r.name, null); + cr.conn.connected(r.name, null); } catch (Exception e) { Slog.w(TAG, "Failure disconnecting service " + r.name + " to connection " + c.get(i).conn.asBinder() + @@ -10526,26 +10536,28 @@ public final class ActivityManagerService extends ActivityManagerNative b.intent.apps.remove(b.client); } - if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent - + ": shouldUnbind=" + b.intent.hasBound); - if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0 - && b.intent.hasBound) { - try { - bumpServiceExecutingLocked(s, "unbind"); - updateOomAdjLocked(s.app); - b.intent.hasBound = false; - // Assume the client doesn't want to know about a rebind; - // we will deal with that later if it asks for one. - b.intent.doRebind = false; - s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent()); - } catch (Exception e) { - Slog.w(TAG, "Exception when unbinding service " + s.shortName, e); - serviceDoneExecutingLocked(s, true); + if (!c.serviceDead) { + if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent + + ": shouldUnbind=" + b.intent.hasBound); + if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0 + && b.intent.hasBound) { + try { + bumpServiceExecutingLocked(s, "unbind"); + updateOomAdjLocked(s.app); + b.intent.hasBound = false; + // Assume the client doesn't want to know about a rebind; + // we will deal with that later if it asks for one. + b.intent.doRebind = false; + s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent()); + } catch (Exception e) { + Slog.w(TAG, "Exception when unbinding service " + s.shortName, e); + serviceDoneExecutingLocked(s, true); + } + } + + if ((c.flags&Context.BIND_AUTO_CREATE) != 0) { + bringDownServiceLocked(s, false); } - } - - if ((c.flags&Context.BIND_AUTO_CREATE) != 0) { - bringDownServiceLocked(s, false); } } @@ -12774,6 +12786,7 @@ public final class ActivityManagerService extends ActivityManagerNative } if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) { ProcessRecord client = cr.binding.client; + int clientAdj = adj; int myHiddenAdj = hiddenAdj; if (myHiddenAdj > client.hiddenAdj) { if (client.hiddenAdj >= VISIBLE_APP_ADJ) { @@ -12782,8 +12795,35 @@ public final class ActivityManagerService extends ActivityManagerNative myHiddenAdj = VISIBLE_APP_ADJ; } } - int clientAdj = computeOomAdjLocked( + clientAdj = computeOomAdjLocked( client, myHiddenAdj, TOP_APP, true); + String adjType = null; + if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) { + // Not doing bind OOM management, so treat + // this guy more like a started service. + if (app.hasShownUi) { + // If this process has shown some UI, let it immediately + // go to the LRU list because it may be pretty heavy with + // UI stuff. We'll tag it with a label just to help + // debug and understand what is going on. + if (adj > clientAdj) { + adjType = "bound-bg-ui-services"; + } + clientAdj = adj; + } else { + if (now >= (s.lastActivity+MAX_SERVICE_INACTIVITY)) { + // This service has not seen activity within + // recent memory, so allow it to drop to the + // LRU list if there is no other reason to keep + // it around. We'll also tag it with a label just + // to help debug and undertand what is going on. + if (adj > clientAdj) { + adjType = "bound-bg-services"; + } + clientAdj = adj; + } + } + } if (adj > clientAdj) { adj = clientAdj >= VISIBLE_APP_ADJ ? clientAdj : VISIBLE_APP_ADJ; @@ -12793,7 +12833,10 @@ public final class ActivityManagerService extends ActivityManagerNative if (client.keeping) { app.keeping = true; } - app.adjType = "service"; + adjType = "service"; + } + if (adjType != null) { + app.adjType = adjType; app.adjTypeCode = ActivityManager.RunningAppProcessInfo .REASON_SERVICE_IN_USE; app.adjSource = cr.binding.client; @@ -13413,7 +13456,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Ignore exceptions. } } - cleanUpApplicationRecordLocked(app, false, -1); + cleanUpApplicationRecordLocked(app, false, true, -1); mRemovedProcesses.remove(i); if (app.persistent) { diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java index 22acda9..0106114 100644 --- a/services/java/com/android/server/am/ConnectionRecord.java +++ b/services/java/com/android/server/am/ConnectionRecord.java @@ -32,6 +32,7 @@ class ConnectionRecord { final int clientLabel; // String resource labeling this client. final PendingIntent clientIntent; // How to launch the client. String stringName; // Caching of toString. + boolean serviceDead; // Well is it? void dump(PrintWriter pw, String prefix) { pw.println(prefix + "binding=" + binding); @@ -61,6 +62,9 @@ class ConnectionRecord { sb.append("ConnectionRecord{"); sb.append(Integer.toHexString(System.identityHashCode(this))); sb.append(' '); + if (serviceDead) { + sb.append("DEAD "); + } sb.append(binding.service.shortName); sb.append(":@"); sb.append(Integer.toHexString(System.identityHashCode(conn.asBinder()))); diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java index a5a6d8e..ce45998 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/java/com/android/server/connectivity/Tethering.java @@ -202,7 +202,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub { sm.start(); } } else { - if (sm != null) { + if (isUsb(iface)) { + // ignore usb0 down after enabling RNDIS + // we will handle disconnect in interfaceRemoved instead + Log.d(TAG, "ignoring interface down for " + iface); + } else if (sm != null) { sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN); mIfaces.remove(iface); } @@ -237,6 +241,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } public void interfaceAdded(String iface) { + if (DEBUG) Log.d(TAG, "interfaceAdded " + iface); boolean found = false; boolean usb = false; if (isWifi(iface)) { @@ -268,6 +273,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } public void interfaceRemoved(String iface) { + if (DEBUG) Log.d(TAG, "interfaceRemoved " + iface); synchronized (mIfaces) { TetherInterfaceSM sm = mIfaces.get(iface); if (sm == null) { @@ -542,6 +548,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } public int setUsbTethering(boolean enable) { + if (DEBUG) Log.d(TAG, "setUsbTethering(" + enable + ")"); UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE); synchronized (this) { diff --git a/services/java/com/android/server/location/GeocoderProxy.java b/services/java/com/android/server/location/GeocoderProxy.java index e3131fe..b38ea13 100644 --- a/services/java/com/android/server/location/GeocoderProxy.java +++ b/services/java/com/android/server/location/GeocoderProxy.java @@ -47,7 +47,9 @@ public class GeocoderProxy { public GeocoderProxy(Context context, String serviceName) { mContext = context; mIntent = new Intent(serviceName); - mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE); + mContext.bindService(mIntent, mServiceConnection, + Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND + | Context.BIND_ALLOW_OOM_MANAGEMENT); } /** @@ -58,7 +60,9 @@ public class GeocoderProxy { synchronized (mMutex) { mContext.unbindService(mServiceConnection); mServiceConnection = new Connection(); - mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE); + mContext.bindService(mIntent, mServiceConnection, + Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND + | Context.BIND_ALLOW_OOM_MANAGEMENT); } } @@ -67,14 +71,12 @@ public class GeocoderProxy { private IGeocodeProvider mProvider; public void onServiceConnected(ComponentName className, IBinder service) { - Log.d(TAG, "onServiceConnected " + className); synchronized (this) { mProvider = IGeocodeProvider.Stub.asInterface(service); } } public void onServiceDisconnected(ComponentName className) { - Log.d(TAG, "onServiceDisconnected " + className); synchronized (this) { mProvider = null; } diff --git a/services/java/com/android/server/location/LocationProviderProxy.java b/services/java/com/android/server/location/LocationProviderProxy.java index 1a1a170..0bc1664 100644 --- a/services/java/com/android/server/location/LocationProviderProxy.java +++ b/services/java/com/android/server/location/LocationProviderProxy.java @@ -28,7 +28,6 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; -import android.os.SystemClock; import android.os.WorkSource; import android.util.Log; @@ -65,7 +64,9 @@ public class LocationProviderProxy implements LocationProviderInterface { mName = name; mIntent = new Intent(serviceName); mHandler = handler; - mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE); + mContext.bindService(mIntent, mServiceConnection, + Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND + | Context.BIND_ALLOW_OOM_MANAGEMENT); } /** @@ -76,7 +77,9 @@ public class LocationProviderProxy implements LocationProviderInterface { synchronized (mMutex) { mContext.unbindService(mServiceConnection); mServiceConnection = new Connection(); - mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE); + mContext.bindService(mIntent, mServiceConnection, + Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND + | Context.BIND_ALLOW_OOM_MANAGEMENT); } } @@ -88,7 +91,6 @@ public class LocationProviderProxy implements LocationProviderInterface { private DummyLocationProvider mCachedAttributes; // synchronized by mMutex public void onServiceConnected(ComponentName className, IBinder service) { - Log.d(TAG, "LocationProviderProxy.onServiceConnected " + className); synchronized (this) { mProvider = ILocationProvider.Stub.asInterface(service); if (mProvider != null) { @@ -98,7 +100,6 @@ public class LocationProviderProxy implements LocationProviderInterface { } public void onServiceDisconnected(ComponentName className) { - Log.d(TAG, "LocationProviderProxy.onServiceDisconnected " + className); synchronized (this) { mProvider = null; } diff --git a/services/java/com/android/server/net/NetworkAlertObserver.java b/services/java/com/android/server/net/NetworkAlertObserver.java new file mode 100644 index 0000000..0d1c3b2 --- /dev/null +++ b/services/java/com/android/server/net/NetworkAlertObserver.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.net; + +import android.net.INetworkManagementEventObserver; + +/** + * @hide + */ +public abstract class NetworkAlertObserver extends INetworkManagementEventObserver.Stub { + @Override + public void interfaceStatusChanged(String iface, boolean up) { + // ignored; interface changes come through ConnectivityService + } + + @Override + public void interfaceRemoved(String iface) { + // ignored; interface changes come through ConnectivityService + } + + @Override + public void interfaceLinkStateChanged(String iface, boolean up) { + // ignored; interface changes come through ConnectivityService + } + + @Override + public void interfaceAdded(String iface) { + // ignored; interface changes come through ConnectivityService + } +} diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java index 435c394..2e1e69b 100644 --- a/services/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java @@ -29,9 +29,8 @@ import static android.net.ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHA import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.ConnectivityManager.TYPE_MOBILE; import static android.net.NetworkPolicy.LIMIT_DISABLED; +import static android.net.NetworkPolicy.SNOOZE_NEVER; import static android.net.NetworkPolicy.WARNING_DISABLED; -import static android.net.NetworkPolicyManager.ACTION_DATA_USAGE_LIMIT; -import static android.net.NetworkPolicyManager.ACTION_DATA_USAGE_WARNING; import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE; import static android.net.NetworkPolicyManager.POLICY_NONE; import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; @@ -56,6 +55,7 @@ import android.app.IProcessObserver; import android.app.Notification; import android.app.PendingIntent; import android.content.BroadcastReceiver; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -64,6 +64,7 @@ import android.content.pm.PackageManager; import android.content.res.Resources; import android.net.ConnectivityManager; import android.net.IConnectivityManager; +import android.net.INetworkManagementEventObserver; import android.net.INetworkPolicyListener; import android.net.INetworkPolicyManager; import android.net.INetworkStatsService; @@ -131,14 +132,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final boolean LOGD = true; private static final boolean LOGV = false; - private static final int VERSION_CURRENT = 1; + private static final int VERSION_INIT = 1; + private static final int VERSION_ADDED_SNOOZE = 2; private static final long KB_IN_BYTES = 1024; private static final long MB_IN_BYTES = KB_IN_BYTES * 1024; private static final long GB_IN_BYTES = MB_IN_BYTES * 1024; - private static final int TYPE_WARNING = 0x1; - private static final int TYPE_LIMIT = 0x2; + // @VisibleForTesting + public static final int TYPE_WARNING = 0x1; + public static final int TYPE_LIMIT = 0x2; + public static final int TYPE_LIMIT_SNOOZED = 0x3; private static final String TAG_POLICY_LIST = "policy-list"; private static final String TAG_NETWORK_POLICY = "network-policy"; @@ -150,6 +154,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final String ATTR_CYCLE_DAY = "cycleDay"; private static final String ATTR_WARNING_BYTES = "warningBytes"; private static final String ATTR_LIMIT_BYTES = "limitBytes"; + private static final String ATTR_LAST_SNOOZE = "lastSnooze"; private static final String ATTR_UID = "uid"; private static final String ATTR_POLICY = "policy"; @@ -162,7 +167,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private final IActivityManager mActivityManager; private final IPowerManager mPowerManager; private final INetworkStatsService mNetworkStats; - private final INetworkManagementService mNetworkManagement; + private final INetworkManagementService mNetworkManager; private final TrustedTime mTime; private IConnectivityManager mConnManager; @@ -173,18 +178,20 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private boolean mScreenOn; private boolean mBackgroundData; - /** Current policy for network templates. */ - private ArrayList<NetworkPolicy> mNetworkPolicy = Lists.newArrayList(); - /** Current derived network rules for ifaces. */ + /** Defined network policies. */ + private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap(); + /** Currently active network rules for ifaces. */ private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap(); - /** Current policy for each UID. */ + /** Defined UID policies. */ private SparseIntArray mUidPolicy = new SparseIntArray(); - /** Current derived rules for each UID. */ + /** Currently derived rules for each UID. */ private SparseIntArray mUidRules = new SparseIntArray(); /** Set of ifaces that are metered. */ private HashSet<String> mMeteredIfaces = Sets.newHashSet(); + /** Set of over-limit templates that have been notified. */ + private HashSet<NetworkTemplate> mOverLimitNotified = Sets.newHashSet(); /** Foreground at both UID and PID granularity. */ private SparseBooleanArray mUidForeground = new SparseBooleanArray(); @@ -202,6 +209,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // TODO: keep whitelist of system-critical services that should never have // rules enforced, such as system, phone, and radio UIDs. + // TODO: migrate notifications to SystemUI + public NetworkPolicyManagerService(Context context, IActivityManager activityManager, IPowerManager powerManager, INetworkStatsService networkStats, INetworkManagementService networkManagement) { @@ -221,7 +230,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mActivityManager = checkNotNull(activityManager, "missing activityManager"); mPowerManager = checkNotNull(powerManager, "missing powerManager"); mNetworkStats = checkNotNull(networkStats, "missing networkStats"); - mNetworkManagement = checkNotNull(networkManagement, "missing networkManagement"); + mNetworkManager = checkNotNull(networkManagement, "missing networkManagement"); mTime = checkNotNull(time, "missing TrustedTime"); mHandlerThread = new HandlerThread(TAG); @@ -256,13 +265,21 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { Slog.e(TAG, "unable to register IProcessObserver", e); } + try { + mNetworkManager.registerObserver(mAlertObserver); + } catch (RemoteException e) { + // ouch, no alert updates means we fall back to + // ACTION_NETWORK_STATS_UPDATED broadcasts. + Slog.e(TAG, "unable to register INetworkManagementEventObserver", e); + } + // TODO: traverse existing processes to know foreground state, or have // activitymanager dispatch current state when new observer attached. final IntentFilter screenFilter = new IntentFilter(); screenFilter.addAction(Intent.ACTION_SCREEN_ON); screenFilter.addAction(Intent.ACTION_SCREEN_OFF); - mContext.registerReceiver(mScreenReceiver, screenFilter); + mContext.registerReceiver(mScreenReceiver, screenFilter, null, mHandler); // watch for network interfaces to be claimed final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION); @@ -272,7 +289,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final IntentFilter packageFilter = new IntentFilter(); packageFilter.addAction(ACTION_PACKAGE_ADDED); packageFilter.addAction(ACTION_UID_REMOVED); - packageFilter.addDataScheme("package"); mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler); // listen for stats update events @@ -393,6 +409,31 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { }; /** + * Observer that watches for {@link INetworkManagementService} alerts. + */ + private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() { + @Override + public void limitReached(String limitName, String iface) { + // only someone like NMS should be calling us + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + + synchronized (mRulesLock) { + if (mMeteredIfaces.contains(iface)) { + try { + // force stats update to make sure we have numbers that + // caused alert to trigger. + mNetworkStats.forceUpdate(); + } catch (RemoteException e) { + Slog.w(TAG, "problem updating network stats"); + } + + updateNotificationsLocked(); + } + } + } + }; + + /** * Check {@link NetworkPolicy} against current {@link INetworkStatsService} * to show visible notifications as needed. */ @@ -415,42 +456,69 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final long start = computeLastCycleBoundary(currentTime, policy); final long end = currentTime; - final long total; + final long totalBytes; try { final NetworkStats stats = mNetworkStats.getSummaryForNetwork( policy.template, start, end); final NetworkStats.Entry entry = stats.getValues(0, null); - total = entry.rxBytes + entry.txBytes; + totalBytes = entry.rxBytes + entry.txBytes; } catch (RemoteException e) { Slog.w(TAG, "problem reading summary for template " + policy.template); continue; } - if (policy.limitBytes != LIMIT_DISABLED && total >= policy.limitBytes) { + if (policy.limitBytes != LIMIT_DISABLED && totalBytes >= policy.limitBytes) { cancelNotification(policy, TYPE_WARNING); - enqueueNotification(policy, TYPE_LIMIT); + + if (policy.lastSnooze >= start) { + cancelNotification(policy, TYPE_LIMIT); + enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes); + } else { + cancelNotification(policy, TYPE_LIMIT_SNOOZED); + enqueueNotification(policy, TYPE_LIMIT, totalBytes); + notifyOverLimitLocked(policy.template); + } + } else { cancelNotification(policy, TYPE_LIMIT); + cancelNotification(policy, TYPE_LIMIT_SNOOZED); + notifyUnderLimitLocked(policy.template); - if (policy.warningBytes != WARNING_DISABLED && total >= policy.warningBytes) { - enqueueNotification(policy, TYPE_WARNING); + if (policy.warningBytes != WARNING_DISABLED && totalBytes >= policy.warningBytes) { + enqueueNotification(policy, TYPE_WARNING, totalBytes); } else { cancelNotification(policy, TYPE_WARNING); } } - } // clear notifications for non-active policies - for (NetworkPolicy policy : mNetworkPolicy) { + for (NetworkPolicy policy : mNetworkPolicy.values()) { if (!mNetworkRules.containsKey(policy)) { cancelNotification(policy, TYPE_WARNING); cancelNotification(policy, TYPE_LIMIT); + cancelNotification(policy, TYPE_LIMIT_SNOOZED); + notifyUnderLimitLocked(policy.template); } } } /** + * Notify that given {@link NetworkTemplate} is over + * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user. + */ + private void notifyOverLimitLocked(NetworkTemplate template) { + if (!mOverLimitNotified.contains(template)) { + mContext.startActivity(buildNetworkOverLimitIntent(template)); + mOverLimitNotified.add(template); + } + } + + private void notifyUnderLimitLocked(NetworkTemplate template) { + mOverLimitNotified.remove(template); + } + + /** * Build unique tag that identifies an active {@link NetworkPolicy} * notification of a specific type, like {@link #TYPE_LIMIT}. */ @@ -462,7 +530,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * Show notification for combined {@link NetworkPolicy} and specific type, * like {@link #TYPE_LIMIT}. Okay to call multiple times. */ - private void enqueueNotification(NetworkPolicy policy, int type) { + private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) { final String tag = buildNotificationTag(policy, type); final Notification.Builder builder = new Notification.Builder(mContext); builder.setOnlyAlertOnce(true); @@ -471,8 +539,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final Resources res = mContext.getResources(); switch (type) { case TYPE_WARNING: { - final String title = res.getString(R.string.data_usage_warning_title); - final String body = res.getString(R.string.data_usage_warning_body, + final CharSequence title = res.getText(R.string.data_usage_warning_title); + final CharSequence body = res.getString(R.string.data_usage_warning_body, Formatter.formatFileSize(mContext, policy.warningBytes)); builder.setSmallIcon(R.drawable.ic_menu_info_details); @@ -480,25 +548,24 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { builder.setContentTitle(title); builder.setContentText(body); - final Intent intent = new Intent(ACTION_DATA_USAGE_WARNING); - intent.addCategory(Intent.CATEGORY_DEFAULT); - intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.template.getMatchRule()); + final Intent intent = buildViewDataUsageIntent(policy.template); builder.setContentIntent(PendingIntent.getActivity( mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); break; } case TYPE_LIMIT: { - final String title; - final String body = res.getString(R.string.data_usage_limit_body); + final CharSequence body = res.getText(R.string.data_usage_limit_body); + + final CharSequence title; switch (policy.template.getMatchRule()) { case MATCH_MOBILE_3G_LOWER: - title = res.getString(R.string.data_usage_3g_limit_title); + title = res.getText(R.string.data_usage_3g_limit_title); break; case MATCH_MOBILE_4G: - title = res.getString(R.string.data_usage_4g_limit_title); + title = res.getText(R.string.data_usage_4g_limit_title); break; default: - title = res.getString(R.string.data_usage_mobile_limit_title); + title = res.getText(R.string.data_usage_mobile_limit_title); break; } @@ -507,9 +574,35 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { builder.setContentTitle(title); builder.setContentText(body); - final Intent intent = new Intent(ACTION_DATA_USAGE_LIMIT); - intent.addCategory(Intent.CATEGORY_DEFAULT); - intent.putExtra(EXTRA_NETWORK_TEMPLATE, policy.template.getMatchRule()); + final Intent intent = buildNetworkOverLimitIntent(policy.template); + builder.setContentIntent(PendingIntent.getActivity( + mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); + break; + } + case TYPE_LIMIT_SNOOZED: { + final long overBytes = totalBytes - policy.limitBytes; + final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body, + Formatter.formatFileSize(mContext, overBytes)); + + final CharSequence title; + switch (policy.template.getMatchRule()) { + case MATCH_MOBILE_3G_LOWER: + title = res.getText(R.string.data_usage_3g_limit_snoozed_title); + break; + case MATCH_MOBILE_4G: + title = res.getText(R.string.data_usage_4g_limit_snoozed_title); + break; + default: + title = res.getText(R.string.data_usage_mobile_limit_snoozed_title); + break; + } + + builder.setSmallIcon(R.drawable.ic_menu_info_details); + builder.setTicker(title); + builder.setContentTitle(title); + builder.setContentText(body); + + final Intent intent = buildViewDataUsageIntent(policy.template); builder.setContentIntent(PendingIntent.getActivity( mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); break; @@ -591,7 +684,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // build list of rules and ifaces to enforce them against mNetworkRules.clear(); final ArrayList<String> ifaceList = Lists.newArrayList(); - for (NetworkPolicy policy : mNetworkPolicy) { + for (NetworkPolicy policy : mNetworkPolicy.values()) { // collect all active ifaces that match this template ifaceList.clear(); @@ -642,11 +735,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { + Arrays.toString(ifaces)); } - // TODO: register for warning notification trigger through NMS + final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED; + final boolean hasWarning = policy.warningBytes != WARNING_DISABLED; - if (policy.limitBytes != NetworkPolicy.LIMIT_DISABLED) { - // remaining "quota" is based on usage in current cycle - final long quota = Math.max(0, policy.limitBytes - total); + if (hasLimit || hasWarning) { + final long quotaBytes; + if (hasLimit) { + // remaining "quota" is based on usage in current cycle + quotaBytes = Math.max(0, policy.limitBytes - total); + } else { + // to track warning alert later, use a high quota + quotaBytes = Long.MAX_VALUE; + } if (ifaces.length > 1) { // TODO: switch to shared quota once NMS supports @@ -655,8 +755,20 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { for (String iface : ifaces) { removeInterfaceQuota(iface); - setInterfaceQuota(iface, quota); - newMeteredIfaces.add(iface); + if (quotaBytes > 0) { + setInterfaceQuota(iface, quotaBytes); + newMeteredIfaces.add(iface); + } + } + } + + if (hasWarning) { + final long alertBytes = Math.max(0, policy.warningBytes - total); + for (String iface : ifaces) { + removeInterfaceAlert(iface); + if (alertBytes > 0) { + setInterfaceAlert(iface, alertBytes); + } } } } @@ -685,7 +797,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // examine to see if any policy is defined for active mobile boolean mobileDefined = false; - for (NetworkPolicy policy : mNetworkPolicy) { + for (NetworkPolicy policy : mNetworkPolicy.values()) { if (policy.template.matches(probeIdent)) { mobileDefined = true; } @@ -704,7 +816,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final int cycleDay = time.monthDay; final NetworkTemplate template = buildTemplateMobileAll(subscriberId); - mNetworkPolicy.add(new NetworkPolicy(template, cycleDay, warningBytes, LIMIT_DISABLED)); + mNetworkPolicy.put(template, new NetworkPolicy( + template, cycleDay, warningBytes, LIMIT_DISABLED, SNOOZE_NEVER)); writePolicyLocked(); } } @@ -723,7 +836,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { in.setInput(fis, null); int type; - int version = VERSION_CURRENT; + int version = VERSION_INIT; while ((type = in.next()) != END_DOCUMENT) { final String tag = in.getName(); if (type == START_TAG) { @@ -736,11 +849,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY); final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES); final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES); + final long lastSnooze; + if (version >= VERSION_ADDED_SNOOZE) { + lastSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE); + } else { + lastSnooze = SNOOZE_NEVER; + } final NetworkTemplate template = new NetworkTemplate( networkTemplate, subscriberId); - mNetworkPolicy.add( - new NetworkPolicy(template, cycleDay, warningBytes, limitBytes)); + mNetworkPolicy.put(template, new NetworkPolicy( + template, cycleDay, warningBytes, limitBytes, lastSnooze)); } else if (TAG_UID_POLICY.equals(tag)) { final int uid = readIntAttribute(in, ATTR_UID); @@ -778,10 +897,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { out.startDocument(null, true); out.startTag(null, TAG_POLICY_LIST); - writeIntAttribute(out, ATTR_VERSION, VERSION_CURRENT); + writeIntAttribute(out, ATTR_VERSION, VERSION_ADDED_SNOOZE); // write all known network policies - for (NetworkPolicy policy : mNetworkPolicy) { + for (NetworkPolicy policy : mNetworkPolicy.values()) { final NetworkTemplate template = policy.template; out.startTag(null, TAG_NETWORK_POLICY); @@ -793,6 +912,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay); writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes); writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes); + writeLongAttribute(out, ATTR_LAST_SNOOZE, policy.lastSnooze); out.endTag(null, TAG_NETWORK_POLICY); } @@ -880,7 +1000,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { synchronized (mRulesLock) { mNetworkPolicy.clear(); for (NetworkPolicy policy : policies) { - mNetworkPolicy.add(policy); + mNetworkPolicy.put(policy.template, policy); } updateNetworkRulesLocked(); @@ -895,7 +1015,34 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG); synchronized (mRulesLock) { - return mNetworkPolicy.toArray(new NetworkPolicy[mNetworkPolicy.size()]); + return mNetworkPolicy.values().toArray(new NetworkPolicy[mNetworkPolicy.size()]); + } + } + + @Override + public void snoozePolicy(NetworkTemplate template) { + mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); + + // try refreshing time source when stale + if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) { + mTime.forceRefresh(); + } + + final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() + : System.currentTimeMillis(); + + synchronized (mRulesLock) { + // find and snooze local policy that matches + final NetworkPolicy policy = mNetworkPolicy.get(template); + if (policy == null) { + throw new IllegalArgumentException("unable to find policy for " + template); + } + + policy.lastSnooze = currentTime; + + updateNetworkRulesLocked(); + updateNotificationsLocked(); + writePolicyLocked(); } } @@ -903,9 +1050,23 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) { mContext.enforceCallingOrSelfPermission(DUMP, TAG); + final HashSet<String> argSet = new HashSet<String>(); + for (String arg : args) { + argSet.add(arg); + } + synchronized (mRulesLock) { + if (argSet.contains("unsnooze")) { + for (NetworkPolicy policy : mNetworkPolicy.values()) { + policy.lastSnooze = SNOOZE_NEVER; + } + writePolicyLocked(); + fout.println("Wiped snooze timestamps"); + return; + } + fout.println("Network policies:"); - for (NetworkPolicy policy : mNetworkPolicy) { + for (NetworkPolicy policy : mNetworkPolicy.values()) { fout.print(" "); fout.println(policy.toString()); } @@ -1124,9 +1285,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }; - private void setInterfaceQuota(String iface, long quota) { + private void setInterfaceQuota(String iface, long quotaBytes) { try { - mNetworkManagement.setInterfaceQuota(iface, quota); + mNetworkManager.setInterfaceQuota(iface, quotaBytes); } catch (IllegalStateException e) { Slog.e(TAG, "problem setting interface quota", e); } catch (RemoteException e) { @@ -1136,7 +1297,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private void removeInterfaceQuota(String iface) { try { - mNetworkManagement.removeInterfaceQuota(iface); + mNetworkManager.removeInterfaceQuota(iface); } catch (IllegalStateException e) { Slog.e(TAG, "problem removing interface quota", e); } catch (RemoteException e) { @@ -1144,9 +1305,29 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + private void setInterfaceAlert(String iface, long alertBytes) { + try { + mNetworkManager.setInterfaceAlert(iface, alertBytes); + } catch (IllegalStateException e) { + Slog.e(TAG, "problem setting interface alert", e); + } catch (RemoteException e) { + Slog.e(TAG, "problem setting interface alert", e); + } + } + + private void removeInterfaceAlert(String iface) { + try { + mNetworkManager.removeInterfaceAlert(iface); + } catch (IllegalStateException e) { + Slog.e(TAG, "problem removing interface alert", e); + } catch (RemoteException e) { + Slog.e(TAG, "problem removing interface alert", e); + } + } + private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) { try { - mNetworkManagement.setUidNetworkRules(uid, rejectOnQuotaInterfaces); + mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces); } catch (IllegalStateException e) { Slog.e(TAG, "problem setting uid rules", e); } catch (RemoteException e) { @@ -1160,6 +1341,24 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return telephony.getSubscriberId(); } + private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) { + final Intent intent = new Intent(); + intent.setComponent(new ComponentName( + "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity")); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(EXTRA_NETWORK_TEMPLATE, template); + return intent; + } + + private static Intent buildViewDataUsageIntent(NetworkTemplate template) { + final Intent intent = new Intent(); + intent.setComponent(new ComponentName( + "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity")); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra(EXTRA_NETWORK_TEMPLATE, template); + return intent; + } + private static void collectKeys(SparseIntArray source, SparseBooleanArray target) { final int size = source.size(); for (int i = 0; i < size; i++) { @@ -1198,7 +1397,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { try { return Long.parseLong(value); } catch (NumberFormatException e) { - throw new ProtocolException("problem parsing " + name + "=" + value + " as int"); + throw new ProtocolException("problem parsing " + name + "=" + value + " as long"); } } diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 9eb1179..88e0fa8 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -20,6 +20,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; +import static libcore.io.OsConstants.S_ISLNK; import com.android.internal.app.IMediaContainerService; import com.android.internal.app.ResolverActivity; @@ -76,6 +77,7 @@ import android.os.Environment; import android.os.FileObserver; import android.os.FileUtils; import android.os.FileUtils.FileStatus; +import android.os.Debug; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; @@ -128,6 +130,9 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; +import libcore.io.ErrnoException; +import libcore.io.Libcore; + /** * Keep track of all those .apks everywhere. * @@ -3338,16 +3343,27 @@ public class PackageManagerService extends IPackageManager.Stub { } else if (nativeLibraryDir.getCanonicalFile().getParent() .equals(dataPathString)) { /* + * Make sure the native library dir isn't a symlink to + * something. If it is, ask installd to remove it and create + * a directory so we can copy to it afterwards. + */ + boolean isSymLink; + try { + isSymLink = S_ISLNK(Libcore.os.lstat(nativeLibraryDir.getPath()).st_mode); + } catch (ErrnoException e) { + // This shouldn't happen, but we'll fail-safe. + isSymLink = true; + } + if (isSymLink) { + mInstaller.unlinkNativeLibraryDirectory(dataPathString); + } + + /* * If this is an internal application or our * nativeLibraryPath points to our data directory, unpack - * the libraries. The native library path pointing to the - * data directory for an application in an ASEC container - * can happen for older apps that existed before an OTA to - * Gingerbread. + * the libraries if necessary. */ - Slog.i(TAG, "Unpacking native libraries for " + path); - mInstaller.unlinkNativeLibraryDirectory(dataPathString); - NativeLibraryHelper.copyNativeBinariesLI(scanFile, nativeLibraryDir); + NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir); } else { Slog.i(TAG, "Linking native library dir for " + path); mInstaller.linkNativeLibraryDirectory(dataPathString, @@ -7930,7 +7946,7 @@ public class PackageManagerService extends IPackageManager.Stub { .unlinkNativeLibraryDirectory(pkg.applicationInfo.dataDir) < 0) { returnCode = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE; } else { - NativeLibraryHelper.copyNativeBinariesLI(new File( + NativeLibraryHelper.copyNativeBinariesIfNeededLI(new File( newCodePath), new File(newNativePath)); } } else { diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java index f183f83..11cb555 100644 --- a/services/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/java/com/android/server/usb/UsbDeviceManager.java @@ -528,10 +528,10 @@ public class UsbDeviceManager { private void updateUsbNotification() { if (mNotificationManager == null || !mUseUsbNotification) return; + int id = NOTIFICATION_NONE; + Resources r = mContext.getResources(); + CharSequence title = null; if (mConnected) { - Resources r = mContext.getResources(); - CharSequence title = null; - int id = NOTIFICATION_NONE; if (containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP)) { title = r.getText( com.android.internal.R.string.usb_mtp_notification_title); @@ -550,16 +550,19 @@ public class UsbDeviceManager { com.android.internal.R.string.usb_accessory_notification_title); id = NOTIFICATION_ACCESSORY; } else { - Slog.e(TAG, "No known USB function in updateUsbNotification"); - } - if (id != mUsbNotificationId) { - // clear notification if title needs changing - if (mUsbNotificationId != NOTIFICATION_NONE) { - mNotificationManager.cancel(mUsbNotificationId); - mUsbNotificationId = NOTIFICATION_NONE; + // There is a different notification for USB tethering so we don't need one here + if (!containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_RNDIS)) { + Slog.e(TAG, "No known USB function in updateUsbNotification"); } } - if (mUsbNotificationId == NOTIFICATION_NONE) { + } + if (id != mUsbNotificationId) { + // clear notification if title needs changing + if (mUsbNotificationId != NOTIFICATION_NONE) { + mNotificationManager.cancel(mUsbNotificationId); + mUsbNotificationId = NOTIFICATION_NONE; + } + if (id != NOTIFICATION_NONE) { CharSequence message = r.getText( com.android.internal.R.string.usb_notification_message); @@ -584,10 +587,6 @@ public class UsbDeviceManager { mNotificationManager.notify(id, notification); mUsbNotificationId = id; } - - } else if (mUsbNotificationId != NOTIFICATION_NONE) { - mNotificationManager.cancel(mUsbNotificationId); - mUsbNotificationId = NOTIFICATION_NONE; } } diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java index 8146fca..b37d1c2 100644 --- a/services/java/com/android/server/wm/DragState.java +++ b/services/java/com/android/server/wm/DragState.java @@ -123,8 +123,8 @@ class DragState { // The drag window covers the entire display mDragWindowHandle.frameLeft = 0; mDragWindowHandle.frameTop = 0; - mDragWindowHandle.frameRight = mService.mDisplay.getRealWidth(); - mDragWindowHandle.frameBottom = mService.mDisplay.getRealHeight(); + mDragWindowHandle.frameRight = mService.mCurDisplayWidth; + mDragWindowHandle.frameBottom = mService.mCurDisplayHeight; } } diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java index 3133a19..1d0857b 100644 --- a/services/java/com/android/server/wm/InputManager.java +++ b/services/java/com/android/server/wm/InputManager.java @@ -64,7 +64,8 @@ public class InputManager { private static native void nativeInit(Context context, Callbacks callbacks, MessageQueue messageQueue); private static native void nativeStart(); - private static native void nativeSetDisplaySize(int displayId, int width, int height); + private static native void nativeSetDisplaySize(int displayId, int width, int height, + int externalWidth, int externalHeight); private static native void nativeSetDisplayOrientation(int displayId, int rotation); private static native int nativeGetScanCodeState(int deviceId, int sourceMask, @@ -144,15 +145,17 @@ public class InputManager { updatePointerSpeedFromSettings(); } - public void setDisplaySize(int displayId, int width, int height) { - if (width <= 0 || height <= 0) { + public void setDisplaySize(int displayId, int width, int height, + int externalWidth, int externalHeight) { + if (width <= 0 || height <= 0 || externalWidth <= 0 || externalHeight <= 0) { throw new IllegalArgumentException("Invalid display id or dimensions."); } if (DEBUG) { - Slog.d(TAG, "Setting display #" + displayId + " size to " + width + "x" + height); + Slog.d(TAG, "Setting display #" + displayId + " size to " + width + "x" + height + + " external size " + externalWidth + "x" + externalHeight); } - nativeSetDisplaySize(displayId, width, height); + nativeSetDisplaySize(displayId, width, height, externalWidth, externalHeight); } public void setDisplayOrientation(int displayId, int rotation) { diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java index 8470918..16af151 100644 --- a/services/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java @@ -25,9 +25,7 @@ import android.graphics.PixelFormat; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; -import android.util.DisplayMetrics; import android.util.Slog; -import android.view.Display; import android.view.Surface; import android.view.SurfaceSession; import android.view.animation.Animation; @@ -41,7 +39,6 @@ class ScreenRotationAnimation { static final int FREEZE_LAYER = WindowManagerService.TYPE_LAYER_MULTIPLIER * 200; final Context mContext; - final Display mDisplay; Surface mSurface; BlackFrame mBlackFrame; int mWidth, mHeight; @@ -58,18 +55,14 @@ class ScreenRotationAnimation { final Transformation mEnterTransformation = new Transformation(); boolean mStarted; - final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); final Matrix mSnapshotInitialMatrix = new Matrix(); final Matrix mSnapshotFinalMatrix = new Matrix(); final Matrix mTmpMatrix = new Matrix(); final float[] mTmpFloats = new float[9]; - public ScreenRotationAnimation(Context context, Display display, SurfaceSession session, - boolean inTransaction) { + public ScreenRotationAnimation(Context context, SurfaceSession session, + boolean inTransaction, int originalWidth, int originalHeight, int originalRotation) { mContext = context; - mDisplay = display; - - display.getRealMetrics(mDisplayMetrics); Bitmap screenshot = Surface.screenshot(0, 0); @@ -83,9 +76,9 @@ class ScreenRotationAnimation { mWidth = screenshot.getWidth(); mHeight = screenshot.getHeight(); - mOriginalRotation = display.getRotation(); - mOriginalWidth = mDisplayMetrics.widthPixels; - mOriginalHeight = mDisplayMetrics.heightPixels; + mOriginalRotation = originalRotation; + mOriginalWidth = originalWidth; + mOriginalHeight = originalHeight; if (!inTransaction) { if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, @@ -106,7 +99,7 @@ class ScreenRotationAnimation { WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG, " FREEZE " + mSurface + ": CREATE"); - setRotation(display.getRotation()); + setRotation(originalRotation); if (mSurface != null) { Rect dirty = new Rect(0, 0, mWidth, mHeight); @@ -212,7 +205,7 @@ class ScreenRotationAnimation { * Returns true if animating. */ public boolean dismiss(SurfaceSession session, long maxAnimationDuration, - float animationScale) { + float animationScale, int finalWidth, int finalHeight) { if (mSurface == null) { // Can't do animation. return false; @@ -248,16 +241,12 @@ class ScreenRotationAnimation { break; } - mDisplay.getRealMetrics(mDisplayMetrics); - // Initialize the animations. This is a hack, redefining what "parent" // means to allow supplying the last and next size. In this definition // "%p" is the original (let's call it "previous") size, and "%" is the // screen's current/new size. - mEnterAnimation.initialize(mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels, - mOriginalWidth, mOriginalHeight); - mExitAnimation.initialize(mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels, - mOriginalWidth, mOriginalHeight); + mEnterAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight); + mExitAnimation.initialize(finalWidth, finalHeight, mOriginalWidth, mOriginalHeight); mStarted = false; mExitAnimation.restrictDuration(maxAnimationDuration); @@ -270,10 +259,8 @@ class ScreenRotationAnimation { Surface.openTransaction(); try { - final int w = mDisplayMetrics.widthPixels; - final int h = mDisplayMetrics.heightPixels; - Rect outer = new Rect(-w, -h, w*2, h*2); - Rect inner = new Rect(0, 0, w, h); + Rect outer = new Rect(-finalWidth, -finalHeight, finalWidth * 2, finalHeight * 2); + Rect inner = new Rect(0, 0, finalWidth, finalHeight); mBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER); } catch (Surface.OutOfResourcesException e) { Slog.w(TAG, "Unable to allocate black surface", e); diff --git a/services/java/com/android/server/wm/StrictModeFlash.java b/services/java/com/android/server/wm/StrictModeFlash.java index 71b5952..768d2db 100644 --- a/services/java/com/android/server/wm/StrictModeFlash.java +++ b/services/java/com/android/server/wm/StrictModeFlash.java @@ -38,9 +38,6 @@ class StrictModeFlash { final int mThickness = 20; public StrictModeFlash(Display display, SurfaceSession session) { - final DisplayMetrics dm = new DisplayMetrics(); - display.getRealMetrics(dm); - try { mSurface = new Surface(session, 0, "StrictModeFlash", -1, 1, 1, PixelFormat.TRANSLUCENT, 0); } catch (Surface.OutOfResourcesException e) { diff --git a/services/java/com/android/server/wm/Watermark.java b/services/java/com/android/server/wm/Watermark.java index 375abe5..5497eb4 100644 --- a/services/java/com/android/server/wm/Watermark.java +++ b/services/java/com/android/server/wm/Watermark.java @@ -50,10 +50,7 @@ class Watermark { int mLastDH; boolean mDrawNeeded; - Watermark(Display display, SurfaceSession session, String[] tokens) { - final DisplayMetrics dm = new DisplayMetrics(); - display.getRealMetrics(dm); - + Watermark(DisplayMetrics dm, SurfaceSession session, String[] tokens) { if (false) { Log.i(WindowManagerService.TAG, "*********************** WATERMARK"); for (int i=0; i<tokens.length; i++) { diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index be21ac0..f8059f5 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -465,6 +465,7 @@ public class WindowManagerService extends IWindowManager.Stub Display mDisplay; final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); + final DisplayMetrics mRealDisplayMetrics = new DisplayMetrics(); final DisplayMetrics mTmpDisplayMetrics = new DisplayMetrics(); final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics(); @@ -5642,15 +5643,14 @@ public class WindowManagerService extends IWindowManager.Stub } config.orientation = orientation; - DisplayMetrics dm = mDisplayMetrics; - mDisplay.getRealMetrics(dm); + // Update real display metrics. + mDisplay.getMetricsWithSize(mRealDisplayMetrics, mCurDisplayWidth, mCurDisplayHeight); - // Override display width and height with what we are computing, - // to be sure they remain consistent. - dm.widthPixels = dm.noncompatWidthPixels = mAppDisplayWidth - = mPolicy.getNonDecorDisplayWidth(mRotation, dw); - dm.heightPixels = dm.noncompatHeightPixels = mAppDisplayHeight - = mPolicy.getNonDecorDisplayHeight(mRotation, dh); + // Update application display metrics. + final DisplayMetrics dm = mDisplayMetrics; + mAppDisplayWidth = mPolicy.getNonDecorDisplayWidth(mRotation, dw); + mAppDisplayHeight = mPolicy.getNonDecorDisplayHeight(mRotation, dh); + mDisplay.getMetricsWithSize(dm, mAppDisplayWidth, mAppDisplayHeight); mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, mCompatDisplayMetrics); @@ -6086,8 +6086,8 @@ public class WindowManagerService extends IWindowManager.Stub } WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); mDisplay = wm.getDefaultDisplay(); - mInitialDisplayWidth = mDisplay.getRealWidth(); - mInitialDisplayHeight = mDisplay.getRealHeight(); + mInitialDisplayWidth = mDisplay.getRawWidth(); + mInitialDisplayHeight = mDisplay.getRawHeight(); int rot = mDisplay.getRotation(); if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { // If the screen is currently rotated, we need to swap the @@ -6098,7 +6098,9 @@ public class WindowManagerService extends IWindowManager.Stub } mBaseDisplayWidth = mCurDisplayWidth = mAppDisplayWidth = mInitialDisplayWidth; mBaseDisplayHeight = mCurDisplayHeight = mAppDisplayHeight = mInitialDisplayHeight; - mInputManager.setDisplaySize(0, mDisplay.getRawWidth(), mDisplay.getRawHeight()); + mInputManager.setDisplaySize(Display.DEFAULT_DISPLAY, + mDisplay.getRawWidth(), mDisplay.getRawHeight(), + mDisplay.getRawExternalWidth(), mDisplay.getRawExternalHeight()); mPolicy.setInitialDisplaySize(mInitialDisplayWidth, mInitialDisplayHeight); } @@ -6602,6 +6604,13 @@ public class WindowManagerService extends IWindowManager.Stub } } + public void getRealDisplaySize(Point size) { + synchronized(mWindowMap) { + size.x = mCurDisplayWidth; + size.y = mCurDisplayHeight; + } + } + public int getMaximumSizeDimension() { synchronized(mWindowMap) { // Do this based on the raw screen size, until we are smarter. @@ -8687,7 +8696,8 @@ public class WindowManagerService extends IWindowManager.Stub } if (mScreenRotationAnimation == null) { mScreenRotationAnimation = new ScreenRotationAnimation(mContext, - mDisplay, mFxSession, inTransaction); + mFxSession, inTransaction, mCurDisplayWidth, mCurDisplayHeight, + mDisplay.getRotation()); } if (!mScreenRotationAnimation.hasScreenshot()) { Surface.freezeDisplay(0); @@ -8717,7 +8727,7 @@ public class WindowManagerService extends IWindowManager.Stub if (CUSTOM_SCREEN_ROTATION && mScreenRotationAnimation != null && mScreenRotationAnimation.hasScreenshot()) { if (mScreenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, - mTransitionAnimationScale)) { + mTransitionAnimationScale, mCurDisplayWidth, mCurDisplayHeight)) { requestAnimationLocked(0); } else { mScreenRotationAnimation = null; @@ -8797,7 +8807,7 @@ public class WindowManagerService extends IWindowManager.Stub if (line != null) { String[] toks = line.split("%"); if (toks != null && toks.length > 0) { - mWatermark = new Watermark(mDisplay, mFxSession, toks); + mWatermark = new Watermark(mRealDisplayMetrics, mFxSession, toks); } } } catch (FileNotFoundException e) { @@ -9063,8 +9073,6 @@ public class WindowManagerService extends IWindowManager.Stub pw.print(mCurDisplayWidth); pw.print("x"); pw.print(mCurDisplayHeight); pw.print(" app="); pw.print(mAppDisplayWidth); pw.print("x"); pw.print(mAppDisplayHeight); - pw.print(" real="); pw.print(mDisplay.getRealWidth()); - pw.print("x"); pw.print(mDisplay.getRealHeight()); pw.print(" raw="); pw.print(mDisplay.getRawWidth()); pw.print("x"); pw.println(mDisplay.getRawHeight()); } else { diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java index d298ff7..cacb3e7 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/java/com/android/server/wm/WindowState.java @@ -497,8 +497,8 @@ final class WindowState implements WindowManagerPolicy.WindowState { } if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) { - mService.updateWallpaperOffsetLocked(this, mService.mDisplay.getRealWidth(), - mService.mDisplay.getRealHeight(), false); + mService.updateWallpaperOffsetLocked(this, + mService.mAppDisplayWidth, mService.mAppDisplayHeight, false); } if (WindowManagerService.localLOGV) { |