summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server')
-rw-r--r--services/java/com/android/server/ConnectivityService.java2
-rw-r--r--services/java/com/android/server/NetworkManagementService.java122
-rw-r--r--services/java/com/android/server/accessibility/AccessibilityManagerService.java9
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java137
-rw-r--r--services/java/com/android/server/am/ConnectionRecord.java4
-rw-r--r--services/java/com/android/server/connectivity/Tethering.java9
-rw-r--r--services/java/com/android/server/location/GeocoderProxy.java10
-rw-r--r--services/java/com/android/server/location/LocationProviderProxy.java11
-rw-r--r--services/java/com/android/server/net/NetworkAlertObserver.java44
-rw-r--r--services/java/com/android/server/net/NetworkPolicyManagerService.java315
-rw-r--r--services/java/com/android/server/pm/PackageManagerService.java32
-rw-r--r--services/java/com/android/server/usb/UsbDeviceManager.java29
-rw-r--r--services/java/com/android/server/wm/DragState.java4
-rw-r--r--services/java/com/android/server/wm/InputManager.java13
-rw-r--r--services/java/com/android/server/wm/ScreenRotationAnimation.java35
-rw-r--r--services/java/com/android/server/wm/StrictModeFlash.java3
-rw-r--r--services/java/com/android/server/wm/Watermark.java5
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java40
-rw-r--r--services/java/com/android/server/wm/WindowState.java4
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) {