Merge "Notification for changed subtree in accessibility mode not fired properly."
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 634fa30..cda2c5f 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -306,6 +306,7 @@
* method to do cleanup when the dialog is dismissed, instead implement
* that in {@link #onStop}.
*/
+ @Override
public void dismiss() {
if (Looper.myLooper() == mHandler.getLooper()) {
dismissDialog();
@@ -325,7 +326,7 @@
}
try {
- mWindowManager.removeView(mDecor);
+ mWindowManager.removeViewImmediate(mDecor);
} finally {
if (mActionMode != null) {
mActionMode.finish();
@@ -334,7 +335,7 @@
mWindow.closeAllPanels();
onStop();
mShowing = false;
-
+
sendDismissMessage();
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index bf1f07b..60d8a75 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -2787,6 +2787,7 @@
setAccessibilityFocus(null, null);
+ mView.assignParent(null);
mView = null;
mAttachInfo.mRootView = null;
mAttachInfo.mSurface = null;
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 6bcf863..f7b85cc 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -335,15 +335,13 @@
}
}
root.die(immediate);
+ if (view != null) {
+ view.assignParent(null);
+ }
}
void doRemoveView(ViewRootImpl root) {
synchronized (mLock) {
- final View view = root.getView();
- if (view != null) {
- view.assignParent(null);
- }
-
final int index = mRoots.indexOf(root);
if (index >= 0) {
mRoots.remove(index);
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index ddc8d82..1991af1 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -6519,7 +6519,7 @@
int viewType = lp.viewType;
final boolean scrapHasTransientState = scrap.hasTransientState();
if (!shouldRecycleViewType(viewType) || scrapHasTransientState) {
- if (viewType != ITEM_VIEW_TYPE_HEADER_OR_FOOTER || scrapHasTransientState) {
+ if (viewType != ITEM_VIEW_TYPE_HEADER_OR_FOOTER && scrapHasTransientState) {
if (mSkippedScrap == null) {
mSkippedScrap = new ArrayList<View>();
}
@@ -6593,7 +6593,7 @@
final boolean scrapHasTransientState = victim.hasTransientState();
if (!shouldRecycleViewType(whichScrap) || scrapHasTransientState) {
// Do not move views that should be ignored
- if (whichScrap != ITEM_VIEW_TYPE_HEADER_OR_FOOTER ||
+ if (whichScrap != ITEM_VIEW_TYPE_HEADER_OR_FOOTER &&
scrapHasTransientState) {
removeDetachedView(victim, false);
}
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index ad23b66..83739f5 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -64,6 +64,7 @@
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.server.NativeDaemonConnector.Command;
+import com.android.server.NativeDaemonConnector.SensitiveArg;
import com.android.server.am.ActivityManagerService;
import com.android.server.pm.PackageManagerService;
import com.android.server.pm.UserManagerService;
@@ -1641,8 +1642,8 @@
int rc = StorageResultCode.OperationSucceeded;
try {
- mConnector.execute("asec", "create", id, sizeMb, fstype, key, ownerUid,
- external ? "1" : "0");
+ mConnector.execute("asec", "create", id, sizeMb, fstype, new SensitiveArg(key),
+ ownerUid, external ? "1" : "0");
} catch (NativeDaemonConnectorException e) {
rc = StorageResultCode.OperationFailedInternalError;
}
@@ -1742,7 +1743,7 @@
int rc = StorageResultCode.OperationSucceeded;
try {
- mConnector.execute("asec", "mount", id, key, ownerUid);
+ mConnector.execute("asec", "mount", id, new SensitiveArg(key), ownerUid);
} catch (NativeDaemonConnectorException e) {
int code = e.getCode();
if (code != VoldResponseCode.OpFailedStorageBusy) {
@@ -2018,7 +2019,7 @@
final NativeDaemonEvent event;
try {
- event = mConnector.execute("cryptfs", "checkpw", password);
+ event = mConnector.execute("cryptfs", "checkpw", new SensitiveArg(password));
final int code = Integer.parseInt(event.getMessage());
if (code == 0) {
@@ -2057,7 +2058,7 @@
}
try {
- mConnector.execute("cryptfs", "enablecrypto", "inplace", password);
+ mConnector.execute("cryptfs", "enablecrypto", "inplace", new SensitiveArg(password));
} catch (NativeDaemonConnectorException e) {
// Encryption failed
return e.getCode();
@@ -2082,7 +2083,7 @@
final NativeDaemonEvent event;
try {
- event = mConnector.execute("cryptfs", "changepw", password);
+ event = mConnector.execute("cryptfs", "changepw", new SensitiveArg(password));
return Integer.parseInt(event.getMessage());
} catch (NativeDaemonConnectorException e) {
// Encryption failed
@@ -2115,7 +2116,7 @@
final NativeDaemonEvent event;
try {
- event = mConnector.execute("cryptfs", "verifypw", password);
+ event = mConnector.execute("cryptfs", "verifypw", new SensitiveArg(password));
Slog.i(TAG, "cryptfs verifypw => " + event.getMessage());
return Integer.parseInt(event.getMessage());
} catch (NativeDaemonConnectorException e) {
@@ -2481,8 +2482,8 @@
int rc = StorageResultCode.OperationSucceeded;
try {
- mConnector.execute(
- "obb", "mount", mObbState.voldPath, hashedKey, mObbState.ownerGid);
+ mConnector.execute("obb", "mount", mObbState.voldPath, new SensitiveArg(hashedKey),
+ mObbState.ownerGid);
} catch (NativeDaemonConnectorException e) {
int code = e.getCode();
if (code != VoldResponseCode.OpFailedStorageBusy) {
diff --git a/services/java/com/android/server/NativeDaemonConnector.java b/services/java/com/android/server/NativeDaemonConnector.java
index abcd8ee..8a8e38d 100644
--- a/services/java/com/android/server/NativeDaemonConnector.java
+++ b/services/java/com/android/server/NativeDaemonConnector.java
@@ -201,9 +201,28 @@
}
/**
+ * Wrapper around argument that indicates it's sensitive and shouldn't be
+ * logged.
+ */
+ public static class SensitiveArg {
+ private final Object mArg;
+
+ public SensitiveArg(Object arg) {
+ mArg = arg;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(mArg);
+ }
+ }
+
+ /**
* Make command for daemon, escaping arguments as needed.
*/
- private void makeCommand(StringBuilder builder, String cmd, Object... args) {
+ @VisibleForTesting
+ static void makeCommand(StringBuilder rawBuilder, StringBuilder logBuilder, int sequenceNumber,
+ String cmd, Object... args) {
if (cmd.indexOf('\0') >= 0) {
throw new IllegalArgumentException("Unexpected command: " + cmd);
}
@@ -211,16 +230,26 @@
throw new IllegalArgumentException("Arguments must be separate from command");
}
- builder.append(cmd);
+ rawBuilder.append(sequenceNumber).append(' ').append(cmd);
+ logBuilder.append(sequenceNumber).append(' ').append(cmd);
for (Object arg : args) {
final String argString = String.valueOf(arg);
if (argString.indexOf('\0') >= 0) {
throw new IllegalArgumentException("Unexpected argument: " + arg);
}
- builder.append(' ');
- appendEscaped(builder, argString);
+ rawBuilder.append(' ');
+ logBuilder.append(' ');
+
+ appendEscaped(rawBuilder, argString);
+ if (arg instanceof SensitiveArg) {
+ logBuilder.append("[scrubbed]");
+ } else {
+ appendEscaped(logBuilder, argString);
+ }
}
+
+ rawBuilder.append('\0');
}
/**
@@ -300,27 +329,27 @@
*/
public NativeDaemonEvent[] execute(int timeout, String cmd, Object... args)
throws NativeDaemonConnectorException {
- final ArrayList<NativeDaemonEvent> events = Lists.newArrayList();
-
- final int sequenceNumber = mSequenceNumber.incrementAndGet();
- final StringBuilder cmdBuilder =
- new StringBuilder(Integer.toString(sequenceNumber)).append(' ');
final long startTime = SystemClock.elapsedRealtime();
- makeCommand(cmdBuilder, cmd, args);
+ final ArrayList<NativeDaemonEvent> events = Lists.newArrayList();
- final String logCmd = cmdBuilder.toString(); /* includes cmdNum, cmd, args */
+ final StringBuilder rawBuilder = new StringBuilder();
+ final StringBuilder logBuilder = new StringBuilder();
+ final int sequenceNumber = mSequenceNumber.incrementAndGet();
+
+ makeCommand(rawBuilder, logBuilder, sequenceNumber, cmd, args);
+
+ final String rawCmd = rawBuilder.toString();
+ final String logCmd = logBuilder.toString();
+
log("SND -> {" + logCmd + "}");
- cmdBuilder.append('\0');
- final String sentCmd = cmdBuilder.toString(); /* logCmd + \0 */
-
synchronized (mDaemonLock) {
if (mOutputStream == null) {
throw new NativeDaemonConnectorException("missing output stream");
} else {
try {
- mOutputStream.write(sentCmd.getBytes(Charsets.UTF_8));
+ mOutputStream.write(rawCmd.getBytes(Charsets.UTF_8));
} catch (IOException e) {
throw new NativeDaemonConnectorException("problem sending command", e);
}
@@ -329,7 +358,7 @@
NativeDaemonEvent event = null;
do {
- event = mResponseQueue.remove(sequenceNumber, timeout, sentCmd);
+ event = mResponseQueue.remove(sequenceNumber, timeout, logCmd);
if (event == null) {
loge("timed-out waiting for response to " + logCmd);
throw new NativeDaemonFailureException(logCmd, event);
@@ -444,10 +473,11 @@
private static class ResponseQueue {
private static class PendingCmd {
- public int cmdNum;
+ public final int cmdNum;
+ public final String logCmd;
+
public BlockingQueue<NativeDaemonEvent> responses =
new ArrayBlockingQueue<NativeDaemonEvent>(10);
- public String request;
// The availableResponseCount member is used to track when we can remove this
// instance from the ResponseQueue.
@@ -465,7 +495,11 @@
// hold references to this instance already so it can be removed from
// mPendingCmds queue.
public int availableResponseCount;
- public PendingCmd(int c, String r) {cmdNum = c; request = r;}
+
+ public PendingCmd(int cmdNum, String logCmd) {
+ this.cmdNum = cmdNum;
+ this.logCmd = logCmd;
+ }
}
private final LinkedList<PendingCmd> mPendingCmds;
@@ -494,7 +528,7 @@
// let any waiter timeout waiting for this
PendingCmd pendingCmd = mPendingCmds.remove();
Slog.e("NativeDaemonConnector.ResponseQueue",
- "Removing request: " + pendingCmd.request + " (" +
+ "Removing request: " + pendingCmd.logCmd + " (" +
pendingCmd.cmdNum + ")");
}
found = new PendingCmd(cmdNum, null);
@@ -512,7 +546,7 @@
// note that the timeout does not count time in deep sleep. If you don't want
// the device to sleep, hold a wakelock
- public NativeDaemonEvent remove(int cmdNum, int timeoutMs, String origCmd) {
+ public NativeDaemonEvent remove(int cmdNum, int timeoutMs, String logCmd) {
PendingCmd found = null;
synchronized (mPendingCmds) {
for (PendingCmd pendingCmd : mPendingCmds) {
@@ -522,7 +556,7 @@
}
}
if (found == null) {
- found = new PendingCmd(cmdNum, origCmd);
+ found = new PendingCmd(cmdNum, logCmd);
mPendingCmds.add(found);
}
found.availableResponseCount--;
@@ -544,7 +578,7 @@
pw.println("Pending requests:");
synchronized (mPendingCmds) {
for (PendingCmd pendingCmd : mPendingCmds) {
- pw.println(" Cmd " + pendingCmd.cmdNum + " - " + pendingCmd.request);
+ pw.println(" Cmd " + pendingCmd.cmdNum + " - " + pendingCmd.logCmd);
}
}
}
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index a78d68b..1622f0f 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -34,7 +34,6 @@
import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
-import android.bluetooth.BluetoothTetheringDataTracker;
import android.content.Context;
import android.net.INetworkManagementEventObserver;
import android.net.InterfaceConfiguration;
@@ -61,6 +60,7 @@
import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.util.Preconditions;
import com.android.server.NativeDaemonConnector.Command;
+import com.android.server.NativeDaemonConnector.SensitiveArg;
import com.android.server.net.LockdownVpnTracker;
import com.google.android.collect.Maps;
@@ -1001,7 +1001,7 @@
} else {
mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
"broadcast", getSecurityType(wifiConfig),
- wifiConfig.preSharedKey);
+ new SensitiveArg(wifiConfig.preSharedKey));
}
mConnector.execute("softap", "startap");
} catch (NativeDaemonConnectorException e) {
@@ -1051,7 +1051,7 @@
} else {
mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
"broadcast", getSecurityType(wifiConfig),
- wifiConfig.preSharedKey);
+ new SensitiveArg(wifiConfig.preSharedKey));
}
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
diff --git a/services/java/com/android/server/content/SyncManager.java b/services/java/com/android/server/content/SyncManager.java
index cf593ce..80c7d88 100644
--- a/services/java/com/android/server/content/SyncManager.java
+++ b/services/java/com/android/server/content/SyncManager.java
@@ -1966,6 +1966,10 @@
for (int i = 0, N = info.periodicSyncs.size(); i < N; i++) {
final Bundle extras = info.periodicSyncs.get(i).first;
final Long periodInMillis = info.periodicSyncs.get(i).second * 1000;
+ // Skip if the period is invalid
+ if (periodInMillis <= 0) {
+ continue;
+ }
// find when this periodic sync was last scheduled to run
final long lastPollTimeAbsolute = status.getPeriodicSyncTime(i);
diff --git a/services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java b/services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java
index 275d807..e2253a2 100644
--- a/services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/NativeDaemonConnectorTest.java
@@ -17,10 +17,13 @@
package com.android.server;
import static com.android.server.NativeDaemonConnector.appendEscaped;
+import static com.android.server.NativeDaemonConnector.makeCommand;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.server.NativeDaemonConnector.SensitiveArg;
+
/**
* Tests for {@link NativeDaemonConnector}.
*/
@@ -67,4 +70,28 @@
appendEscaped(builder, "caf\u00E9 c\u00F6ffee");
assertEquals("\"caf\u00E9 c\u00F6ffee\"", builder.toString());
}
+
+ public void testSensitiveArgs() throws Exception {
+ final StringBuilder rawBuilder = new StringBuilder();
+ final StringBuilder logBuilder = new StringBuilder();
+
+ rawBuilder.setLength(0);
+ logBuilder.setLength(0);
+ makeCommand(rawBuilder, logBuilder, 1, "foo", "bar", "baz");
+ assertEquals("1 foo bar baz\0", rawBuilder.toString());
+ assertEquals("1 foo bar baz", logBuilder.toString());
+
+ rawBuilder.setLength(0);
+ logBuilder.setLength(0);
+ makeCommand(rawBuilder, logBuilder, 1, "foo", new SensitiveArg("bar"), "baz");
+ assertEquals("1 foo bar baz\0", rawBuilder.toString());
+ assertEquals("1 foo [scrubbed] baz", logBuilder.toString());
+
+ rawBuilder.setLength(0);
+ logBuilder.setLength(0);
+ makeCommand(rawBuilder, logBuilder, 1, "foo", new SensitiveArg("foo bar"), "baz baz",
+ new SensitiveArg("wat"));
+ assertEquals("1 foo \"foo bar\" \"baz baz\" wat\0", rawBuilder.toString());
+ assertEquals("1 foo [scrubbed] \"baz baz\" [scrubbed]", logBuilder.toString());
+ }
}