Merge "Remove broken code for mounting encrypted OBB files"
diff --git a/core/java/android/util/NtpTrustedTime.java b/core/java/android/util/NtpTrustedTime.java
index 40beab3..aebc5e8 100644
--- a/core/java/android/util/NtpTrustedTime.java
+++ b/core/java/android/util/NtpTrustedTime.java
@@ -33,6 +33,9 @@
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.io.PrintWriter;
+import java.time.Duration;
+import java.time.Instant;
 import java.util.Objects;
 import java.util.function.Supplier;
 
@@ -96,8 +99,8 @@
         @Override
         public String toString() {
             return "TimeResult{"
-                    + "mTimeMillis=" + mTimeMillis
-                    + ", mElapsedRealtimeMillis=" + mElapsedRealtimeMillis
+                    + "mTimeMillis=" + Instant.ofEpochMilli(mTimeMillis)
+                    + ", mElapsedRealtimeMillis=" + Duration.ofMillis(mElapsedRealtimeMillis)
                     + ", mCertaintyMillis=" + mCertaintyMillis
                     + '}';
         }
@@ -131,6 +134,14 @@
         }
     };
 
+    /** An in-memory config override for use during tests. */
+    @Nullable
+    private String mHostnameForTests;
+
+    /** An in-memory config override for use during tests. */
+    @Nullable
+    private Duration mTimeoutForTests;
+
     // Declared volatile and accessed outside of synchronized blocks to avoid blocking reads during
     // forceRefresh().
     private volatile TimeResult mTimeResult;
@@ -148,12 +159,23 @@
         return sSingleton;
     }
 
+    /**
+     * Overrides the NTP server config for tests. Passing {@code null} to a parameter clears the
+     * test value, i.e. so the normal value will be used next time.
+     */
+    public void setServerConfigForTests(@Nullable String hostname, @Nullable Duration timeout) {
+        synchronized (this) {
+            mHostnameForTests = hostname;
+            mTimeoutForTests = timeout;
+        }
+    }
+
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public boolean forceRefresh() {
         synchronized (this) {
             NtpConnectionInfo connectionInfo = getNtpConnectionInfo();
             if (connectionInfo == null) {
-                // missing server config, so no trusted time available
+                // missing server config, so no NTP time available
                 if (LOGD) Log.d(TAG, "forceRefresh: invalid server config");
                 return false;
             }
@@ -290,6 +312,14 @@
         int getTimeoutMillis() {
             return mTimeoutMillis;
         }
+
+        @Override
+        public String toString() {
+            return "NtpConnectionInfo{"
+                    + "mServer='" + mServer + '\''
+                    + ", mTimeoutMillis=" + mTimeoutMillis
+                    + '}';
+        }
     }
 
     @GuardedBy("this")
@@ -297,17 +327,41 @@
         final ContentResolver resolver = mContext.getContentResolver();
 
         final Resources res = mContext.getResources();
-        final String defaultServer = res.getString(
-                com.android.internal.R.string.config_ntpServer);
-        final int defaultTimeoutMillis = res.getInteger(
-                com.android.internal.R.integer.config_ntpTimeout);
 
-        final String secureServer = Settings.Global.getString(
-                resolver, Settings.Global.NTP_SERVER);
-        final int timeoutMillis = Settings.Global.getInt(
-                resolver, Settings.Global.NTP_TIMEOUT, defaultTimeoutMillis);
+        final String hostname;
+        if (mHostnameForTests != null) {
+            hostname = mHostnameForTests;
+        } else {
+            String serverGlobalSetting =
+                    Settings.Global.getString(resolver, Settings.Global.NTP_SERVER);
+            if (serverGlobalSetting != null) {
+                hostname = serverGlobalSetting;
+            } else {
+                hostname = res.getString(com.android.internal.R.string.config_ntpServer);
+            }
+        }
 
-        final String server = secureServer != null ? secureServer : defaultServer;
-        return TextUtils.isEmpty(server) ? null : new NtpConnectionInfo(server, timeoutMillis);
+        final int timeoutMillis;
+        if (mTimeoutForTests != null) {
+            timeoutMillis = (int) mTimeoutForTests.toMillis();
+        } else {
+            int defaultTimeoutMillis =
+                    res.getInteger(com.android.internal.R.integer.config_ntpTimeout);
+            timeoutMillis = Settings.Global.getInt(
+                    resolver, Settings.Global.NTP_TIMEOUT, defaultTimeoutMillis);
+        }
+        return TextUtils.isEmpty(hostname) ? null : new NtpConnectionInfo(hostname, timeoutMillis);
+    }
+
+    /** Prints debug information. */
+    public void dump(PrintWriter pw) {
+        synchronized (this) {
+            pw.println("getNtpConnectionInfo()=" + getNtpConnectionInfo());
+            pw.println("mTimeResult=" + mTimeResult);
+            if (mTimeResult != null) {
+                pw.println("mTimeResult.getAgeMillis()="
+                        + Duration.ofMillis(mTimeResult.getAgeMillis()));
+            }
+        }
     }
 }
diff --git a/core/res/OWNERS b/core/res/OWNERS
index e241dd6..b7df255 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -25,6 +25,10 @@
 tsuji@google.com
 yamasani@google.com
 
+# Resources finalization
+per-file res/xml/public-staging.xml = file:/tools/aapt2/OWNERS
+per-file res/xml/public-final.xml = file:/tools/aapt2/OWNERS
+
 # Multiuser
 per-file res/xml/config_user_types.xml = file:/MULTIUSER_OWNERS
 
diff --git a/identity/java/android/security/identity/CredentialDataRequest.java b/identity/java/android/security/identity/CredentialDataRequest.java
index 2a47a02..3482384 100644
--- a/identity/java/android/security/identity/CredentialDataRequest.java
+++ b/identity/java/android/security/identity/CredentialDataRequest.java
@@ -153,7 +153,15 @@
         /**
          * Sets whether to allow using an authentication key which use count has been exceeded.
          *
-         * By default this is set to true.
+         * <p>This is useful in situations where the application hasn't had a chance to renew
+         * authentication keys, for example if the device hasn't been connected to the Internet or
+         * if the issuing authority server has been down.
+         *
+         * <p>The reason this could be useful is that the privacy risk of reusing an authentication
+         * key for a credential presentation could be significantly smaller compared to the
+         * inconvenience of not being able to present the credential at all.
+         *
+         * <p>By default this is set to true.
          *
          * @param allowUsingExhaustedKeys whether to allow using an authentication key which use
          *                                count has been exceeded if no other key is available.
@@ -167,7 +175,16 @@
         /**
          * Sets whether to allow using an authentication key which is expired.
          *
-         * By default this is set to false.
+         * <p>This is useful in situations where the application hasn't had a chance to renew
+         * authentication keys, for example if the device hasn't been connected to the Internet or
+         * if the issuing authority server has been down.
+         *
+         * <p>The reason this could be useful is that many verifiers are likely to accept a
+         * credential presentation using an expired authentication key (the credential itself
+         * wouldn't be expired) and it's likely better for the holder to be able to do this than
+         * not present their credential at all.
+         *
+         * <p>By default this is set to false.
          *
          * @param allowUsingExpiredKeys whether to allow using an authentication key which is
          *                              expired if no other key is available.
@@ -181,7 +198,12 @@
         /**
          * Sets whether to increment the use-count for the authentication key used.
          *
-         * By default this is set to true.
+         * <p>Not incrementing the use-count for an authentication key is useful in situations
+         * where the authentication key is known with certainty to not be leaked. For example,
+         * consider an application doing a credential presentation for the sole purpose of
+         * displaying the credential data to the user (not for verification).
+         *
+         * <p>By default this is set to true.
          *
          * @param incrementUseCount whether to increment the use count of the authentication
          *                          key used.
diff --git a/identity/java/android/security/identity/PresentationSession.java b/identity/java/android/security/identity/PresentationSession.java
index afaafce..6cde611 100644
--- a/identity/java/android/security/identity/PresentationSession.java
+++ b/identity/java/android/security/identity/PresentationSession.java
@@ -26,6 +26,9 @@
 /**
  * Class for presenting multiple documents to a remote verifier.
  *
+ * <p>This should be used for all interactions with a remote verifier instead of the now deprecated
+ * {@link IdentityCredential#getEntries(byte[], Map, byte[], byte[])} method.
+ *
  * Use {@link IdentityCredentialStore#createPresentationSession(int)} to create a {@link
  * PresentationSession} instance.
  */
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateService.java b/services/core/java/com/android/server/NetworkTimeUpdateService.java
index 1e534b7..186ff62 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateService.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.app.timedetector.NetworkTimeSuggestion;
@@ -45,12 +46,12 @@
 import android.util.Log;
 import android.util.NtpTrustedTime;
 import android.util.NtpTrustedTime.TimeResult;
-import android.util.TimeUtils;
 
 import com.android.internal.util.DumpUtils;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.time.Duration;
 
 /**
  * Monitors the network time. If looking up the network time fails for some reason, it tries a few
@@ -191,6 +192,19 @@
         return success;
     }
 
+    /**
+     * Overrides the NTP server config for tests. Passing {@code null} to a parameter clears the
+     * test value, i.e. so the normal value will be used next time.
+     */
+    void setServerConfigForTests(@Nullable String hostname, @Nullable Duration timeout) {
+        mContext.enforceCallingPermission(
+                android.Manifest.permission.SET_TIME, "set NTP server config for tests");
+
+        mLocalLog.log("Setting server config for tests: hostname=" + hostname
+                + ", timeout=" + timeout);
+        mTime.setServerConfigForTests(hostname, timeout);
+    }
+
     private void onPollNetworkTime(int event) {
         // If we don't have any default network, don't bother.
         if (mDefaultNetwork == null) return;
@@ -349,17 +363,14 @@
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
-        pw.print("PollingIntervalMs: ");
-        TimeUtils.formatDuration(mPollingIntervalMs, pw);
-        pw.print("\nPollingIntervalShorterMs: ");
-        TimeUtils.formatDuration(mPollingIntervalShorterMs, pw);
-        pw.println("\nTryAgainTimesMax: " + mTryAgainTimesMax);
-        pw.println("\nTryAgainCounter: " + mTryAgainCounter);
-        NtpTrustedTime.TimeResult ntpResult = mTime.getCachedTimeResult();
-        pw.println("NTP cache result: " + ntpResult);
-        if (ntpResult != null) {
-            pw.println("NTP result age: " + ntpResult.getAgeMillis());
-        }
+        pw.println("mPollingIntervalMs=" + Duration.ofMillis(mPollingIntervalMs));
+        pw.println("mPollingIntervalShorterMs=" + Duration.ofMillis(mPollingIntervalShorterMs));
+        pw.println("mTryAgainTimesMax=" + mTryAgainTimesMax);
+        pw.println("mTryAgainCounter=" + mTryAgainCounter);
+        pw.println();
+        pw.println("NtpTrustedTime:");
+        mTime.dump(pw);
+        pw.println();
         pw.println("Local logs:");
         mLocalLog.dump(fd, pw, args);
         pw.println();
diff --git a/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java b/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
index dc93023..464af01 100644
--- a/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
+++ b/services/core/java/com/android/server/NetworkTimeUpdateServiceShellCommand.java
@@ -20,6 +20,7 @@
 import android.os.ShellCommand;
 
 import java.io.PrintWriter;
+import java.time.Duration;
 import java.util.Objects;
 
 /** Implements the shell command interface for {@link NetworkTimeUpdateService}. */
@@ -40,6 +41,13 @@
      */
     private static final String SHELL_COMMAND_FORCE_REFRESH = "force_refresh";
 
+    /**
+     * A shell command that sets the NTP server config for tests. Config is cleared on reboot.
+     */
+    private static final String SHELL_COMMAND_SET_SERVER_CONFIG = "set_server_config";
+    private static final String SET_SERVER_CONFIG_HOSTNAME_ARG = "--hostname";
+    private static final String SET_SERVER_CONFIG_TIMEOUT_ARG = "--timeout_millis";
+
     @NonNull
     private final NetworkTimeUpdateService mNetworkTimeUpdateService;
 
@@ -58,6 +66,8 @@
                 return runClearTime();
             case SHELL_COMMAND_FORCE_REFRESH:
                 return runForceRefresh();
+            case SHELL_COMMAND_SET_SERVER_CONFIG:
+                return runSetServerConfig();
             default: {
                 return handleDefaultCommands(cmd);
             }
@@ -75,6 +85,29 @@
         return 0;
     }
 
+    private int runSetServerConfig() {
+        String hostname = null;
+        Duration timeout = null;
+        String opt;
+        while ((opt = getNextArg()) != null) {
+            switch (opt) {
+                case SET_SERVER_CONFIG_HOSTNAME_ARG: {
+                    hostname = getNextArgRequired();
+                    break;
+                }
+                case SET_SERVER_CONFIG_TIMEOUT_ARG: {
+                    timeout = Duration.ofMillis(Integer.parseInt(getNextArgRequired()));
+                    break;
+                }
+                default: {
+                    throw new IllegalArgumentException("Unknown option: " + opt);
+                }
+            }
+        }
+        mNetworkTimeUpdateService.setServerConfigForTests(hostname, timeout);
+        return 0;
+    }
+
     @Override
     public void onHelp() {
         final PrintWriter pw = getOutPrintWriter();
@@ -85,6 +118,12 @@
         pw.printf("    Clears the latest time.\n");
         pw.printf("  %s\n", SHELL_COMMAND_FORCE_REFRESH);
         pw.printf("    Refreshes the latest time. Prints whether it was successful.\n");
+        pw.printf("  %s\n", SHELL_COMMAND_SET_SERVER_CONFIG);
+        pw.printf("    Sets the NTP server config for tests. The config is not persisted.\n");
+        pw.printf("      Options: [%s <hostname>] [%s <millis>]\n",
+                SET_SERVER_CONFIG_HOSTNAME_ARG, SET_SERVER_CONFIG_TIMEOUT_ARG);
+        pw.printf("      Each key/value is optional and must be specified to override the\n");
+        pw.printf("      normal value, not specifying a key causes it to reset to the original.\n");
         pw.println();
     }
 }
diff --git a/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java b/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java
index 62b701a..11c451e 100644
--- a/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java
+++ b/services/core/java/com/android/server/clipboard/EmulatorClipboardMonitor.java
@@ -18,6 +18,7 @@
 
 import android.annotation.Nullable;
 import android.content.ClipData;
+import android.os.SystemProperties;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
@@ -39,6 +40,8 @@
     private static final String PIPE_NAME = "pipe:clipboard";
     private static final int HOST_PORT = 5000;
     private final Thread mHostMonitorThread;
+    private static final boolean LOG_CLIBOARD_ACCESS =
+            SystemProperties.getBoolean("ro.boot.qemu.log_clipboard_access", false);
     private FileDescriptor mPipe = null;
 
     private static byte[] createOpenHandshake() {
@@ -132,6 +135,9 @@
                                                        new String[]{"text/plain"},
                                                        new ClipData.Item(str));
 
+                    if (LOG_CLIBOARD_ACCESS) {
+                        Slog.i(TAG, "Setting the guest clipboard to '" + str + "'");
+                    }
                     setAndroidClipboard.accept(clip);
                 } catch (ErrnoException | InterruptedIOException e) {
                     closePipe();
@@ -156,6 +162,10 @@
     }
 
     private void setHostClipboardImpl(final String value) {
+        if (LOG_CLIBOARD_ACCESS) {
+            Slog.i(TAG, "Setting the host clipboard to '" + value + "'");
+        }
+
         try {
             if (isPipeOpened()) {
                 sendMessage(value.getBytes());
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 9f58f65..0a77430 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -991,10 +991,10 @@
             final IntentFilter packageFilter = new IntentFilter();
             packageFilter.addAction(ACTION_PACKAGE_ADDED);
             packageFilter.addDataScheme("package");
-            mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler);
+            mContext.registerReceiverForAllUsers(mPackageReceiver, packageFilter, null, mHandler);
 
             // listen for UID changes to update policy
-            mContext.registerReceiver(
+            mContext.registerReceiverForAllUsers(
                     mUidRemovedReceiver, new IntentFilter(ACTION_UID_REMOVED), null, mHandler);
 
             // listen for user changes to update policy
diff --git a/services/tests/wmtests/src/com/android/server/policy/OWNERS b/services/tests/wmtests/src/com/android/server/policy/OWNERS
new file mode 100644
index 0000000..27891dc
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/policy/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/policy/OWNERS
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 741f33f..87c75be 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -267,7 +267,8 @@
     @Test
     public void testUpdateSleep() {
         doCallRealMethod().when(mWm.mRoot).hasAwakeDisplay();
-        mSupervisor.mGoingToSleepWakeLock = mock(PowerManager.WakeLock.class);
+        mSupervisor.mGoingToSleepWakeLock =
+                mSystemServicesTestRule.createStubbedWakeLock(true /* needVerification */);
         final Task rootHomeTask = mWm.mRoot.getDefaultTaskDisplayArea().getOrCreateRootHomeTask();
         final ActivityRecord homeActivity = new ActivityBuilder(mAtm).setTask(rootHomeTask).build();
         final ActivityRecord topActivity = new ActivityBuilder(mAtm).setCreateTask(true).build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 8e7ba4bc..0b2399b1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -102,6 +102,10 @@
     static int sNextTaskId = 100;
 
     private static final int[] TEST_USER_PROFILE_IDS = {};
+    /** Use a real static object so there won't be NPE in finalize() after clearInlineMocks(). */
+    private static final PowerManager.WakeLock sWakeLock = getInstrumentation().getContext()
+            .getSystemService(PowerManager.class).newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+    private PowerManager.WakeLock mStubbedWakeLock;
 
     private Description mDescription;
     private Context mContext;
@@ -196,7 +200,8 @@
         // Prevent "WakeLock finalized while still held: SCREEN_FROZEN".
         final PowerManager pm = mock(PowerManager.class);
         doReturn(pm).when(mContext).getSystemService(eq(Context.POWER_SERVICE));
-        doReturn(mock(PowerManager.WakeLock.class)).when(pm).newWakeLock(anyInt(), anyString());
+        mStubbedWakeLock = createStubbedWakeLock(false /* needVerification */);
+        doReturn(mStubbedWakeLock).when(pm).newWakeLock(anyInt(), anyString());
 
         // DisplayManagerInternal
         final DisplayManagerInternal dmi = mock(DisplayManagerInternal.class);
@@ -403,6 +408,16 @@
         return mPowerManagerWrapper;
     }
 
+    /** Creates a no-op wakelock object. */
+    PowerManager.WakeLock createStubbedWakeLock(boolean needVerification) {
+        if (needVerification) {
+            return mock(PowerManager.WakeLock.class, Mockito.withSettings()
+                    .spiedInstance(sWakeLock).defaultAnswer(Mockito.RETURNS_DEFAULTS));
+        }
+        return mock(PowerManager.WakeLock.class, Mockito.withSettings()
+                .spiedInstance(sWakeLock).stubOnly());
+    }
+
     void setSurfaceFactory(Supplier<Surface> factory) {
         mSurfaceFactory = factory;
     }
@@ -558,7 +573,7 @@
             // unit test version does not handle launch wake lock
             doNothing().when(this).acquireLaunchWakelock();
 
-            mLaunchingActivityWakeLock = mock(PowerManager.WakeLock.class);
+            mLaunchingActivityWakeLock = mStubbedWakeLock;
 
             initialize();