Snap for 12695596 from 78a56d22917ce51899a84e39b355faf888db2629 to 25Q1-release

Change-Id: I425f024bebfff80a36cf2ba7e2fd1321fe0b6b07
diff --git a/bpf/netd/Android.bp b/bpf/netd/Android.bp
index fe4d999..473c8c9 100644
--- a/bpf/netd/Android.bp
+++ b/bpf/netd/Android.bp
@@ -82,7 +82,6 @@
         "libcutils",
         "liblog",
         "libnetdutils",
-        "libprocessgroup",
     ],
     compile_multilib: "both",
     multilib: {
diff --git a/bpf/netd/BpfBaseTest.cpp b/bpf/netd/BpfBaseTest.cpp
index 34dfbb4..4b8a04e 100644
--- a/bpf/netd/BpfBaseTest.cpp
+++ b/bpf/netd/BpfBaseTest.cpp
@@ -29,7 +29,6 @@
 #include <gtest/gtest.h>
 
 #include <cutils/qtaguid.h>
-#include <processgroup/processgroup.h>
 
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
@@ -54,13 +53,6 @@
     BpfBasicTest() {}
 };
 
-TEST_F(BpfBasicTest, TestCgroupMounted) {
-    std::string cg2_path;
-    ASSERT_EQ(true, CgroupGetControllerPath(CGROUPV2_HIERARCHY_NAME, &cg2_path));
-    ASSERT_EQ(0, access(cg2_path.c_str(), R_OK));
-    ASSERT_EQ(0, access((cg2_path + "/cgroup.controllers").c_str(), R_OK));
-}
-
 TEST_F(BpfBasicTest, TestTagSocket) {
     BpfMap<uint64_t, UidTagValue> cookieTagMap(COOKIE_TAG_MAP_PATH);
     ASSERT_TRUE(cookieTagMap.isValid());
diff --git a/bpf/netd/BpfHandler.cpp b/bpf/netd/BpfHandler.cpp
index 50e0329..340acda 100644
--- a/bpf/netd/BpfHandler.cpp
+++ b/bpf/netd/BpfHandler.cpp
@@ -97,6 +97,7 @@
         ALOGE("Failed to open the cgroup directory: %s", strerror(err));
         return statusFromErrno(err, "Open the cgroup directory failed");
     }
+
     RETURN_IF_NOT_OK(checkProgramAccessible(XT_BPF_ALLOWLIST_PROG_PATH));
     RETURN_IF_NOT_OK(checkProgramAccessible(XT_BPF_DENYLIST_PROG_PATH));
     RETURN_IF_NOT_OK(checkProgramAccessible(XT_BPF_EGRESS_PROG_PATH));
diff --git a/common/networksecurity_flags.aconfig b/common/networksecurity_flags.aconfig
index 6438ba4..4a83af4 100644
--- a/common/networksecurity_flags.aconfig
+++ b/common/networksecurity_flags.aconfig
@@ -8,3 +8,12 @@
     bug: "319829948"
     is_fixed_read_only: true
 }
+
+flag {
+    name: "certificate_transparency_job"
+    is_exported: true
+    namespace: "network_security"
+    description: "Enable daily job service for certificate transparency instead of flags listener"
+    bug: "319829948"
+    is_fixed_read_only: true
+}
diff --git a/networksecurity/service/src/com/android/server/net/ct/CertificateTransparencyDownloader.java b/networksecurity/service/src/com/android/server/net/ct/CertificateTransparencyDownloader.java
index f86d127..d53f007 100644
--- a/networksecurity/service/src/com/android/server/net/ct/CertificateTransparencyDownloader.java
+++ b/networksecurity/service/src/com/android/server/net/ct/CertificateTransparencyDownloader.java
@@ -88,12 +88,17 @@
     }
 
     void setPublicKey(String publicKey) throws GeneralSecurityException {
-        mPublicKey =
-                Optional.of(
-                        KeyFactory.getInstance("RSA")
-                                .generatePublic(
-                                        new X509EncodedKeySpec(
-                                                Base64.getDecoder().decode(publicKey))));
+        try {
+            mPublicKey =
+                    Optional.of(
+                            KeyFactory.getInstance("RSA")
+                                    .generatePublic(
+                                            new X509EncodedKeySpec(
+                                                    Base64.getDecoder().decode(publicKey))));
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "Invalid public key Base64 encoding", e);
+            mPublicKey = Optional.empty();
+        }
     }
 
     @VisibleForTesting
diff --git a/networksecurity/service/src/com/android/server/net/ct/CertificateTransparencyFlagsListener.java b/networksecurity/service/src/com/android/server/net/ct/CertificateTransparencyFlagsListener.java
index 0ae982d..93a7064 100644
--- a/networksecurity/service/src/com/android/server/net/ct/CertificateTransparencyFlagsListener.java
+++ b/networksecurity/service/src/com/android/server/net/ct/CertificateTransparencyFlagsListener.java
@@ -16,7 +16,6 @@
 package com.android.server.net.ct;
 
 import android.annotation.RequiresApi;
-import android.content.Context;
 import android.os.Build;
 import android.provider.DeviceConfig;
 import android.provider.DeviceConfig.Properties;
@@ -35,10 +34,11 @@
     private final DataStore mDataStore;
     private final CertificateTransparencyDownloader mCertificateTransparencyDownloader;
 
-    CertificateTransparencyFlagsListener(Context context) {
-        mDataStore = new DataStore(Config.PREFERENCES_FILE);
-        mCertificateTransparencyDownloader =
-                new CertificateTransparencyDownloader(context, mDataStore);
+    CertificateTransparencyFlagsListener(
+            DataStore dataStore,
+            CertificateTransparencyDownloader certificateTransparencyDownloader) {
+        mDataStore = dataStore;
+        mCertificateTransparencyDownloader = certificateTransparencyDownloader;
     }
 
     void initialize() {
diff --git a/networksecurity/service/src/com/android/server/net/ct/CertificateTransparencyJob.java b/networksecurity/service/src/com/android/server/net/ct/CertificateTransparencyJob.java
new file mode 100644
index 0000000..6fbf0ba
--- /dev/null
+++ b/networksecurity/service/src/com/android/server/net/ct/CertificateTransparencyJob.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2024 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.ct;
+
+import android.annotation.RequiresApi;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Build;
+import android.os.SystemClock;
+import android.provider.DeviceConfig;
+import android.util.Log;
+
+import java.util.HashMap;
+
+/** Implementation of the Certificate Transparency job */
+@RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
+public class CertificateTransparencyJob extends BroadcastReceiver {
+
+    private static final String TAG = "CertificateTransparencyJob";
+
+    private static final String ACTION_JOB_START = "com.android.server.net.ct.action.JOB_START";
+
+    private final Context mContext;
+    private final DataStore mDataStore;
+    private final CertificateTransparencyDownloader mCertificateTransparencyDownloader;
+    // TODO(b/374692404): remove dependency to flags.
+    private final CertificateTransparencyFlagsListener mFlagsListener;
+    private final AlarmManager mAlarmManager;
+
+    /** Creates a new {@link CertificateTransparencyJob} object. */
+    public CertificateTransparencyJob(
+            Context context,
+            DataStore dataStore,
+            CertificateTransparencyDownloader certificateTransparencyDownloader,
+            CertificateTransparencyFlagsListener flagsListener) {
+        mContext = context;
+        mFlagsListener = flagsListener;
+        mDataStore = dataStore;
+        mCertificateTransparencyDownloader = certificateTransparencyDownloader;
+        mAlarmManager = context.getSystemService(AlarmManager.class);
+    }
+
+    void initialize() {
+        mDataStore.load();
+        mCertificateTransparencyDownloader.initialize();
+
+        mContext.registerReceiver(
+                this, new IntentFilter(ACTION_JOB_START), Context.RECEIVER_EXPORTED);
+        mAlarmManager.setInexactRepeating(
+                AlarmManager.ELAPSED_REALTIME,
+                SystemClock.elapsedRealtime(), // schedule first job at earliest convenient time.
+                AlarmManager.INTERVAL_DAY,
+                PendingIntent.getBroadcast(
+                        mContext, 0, new Intent(ACTION_JOB_START), PendingIntent.FLAG_IMMUTABLE));
+
+        if (Config.DEBUG) {
+            Log.d(TAG, "CertificateTransparencyJob scheduled successfully.");
+        }
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (!ACTION_JOB_START.equals(intent.getAction())) {
+            Log.w(TAG, "Received unexpected broadcast with action " + intent);
+            return;
+        }
+        mFlagsListener.onPropertiesChanged(
+                new DeviceConfig.Properties(Config.NAMESPACE_NETWORK_SECURITY, new HashMap<>()));
+    }
+}
diff --git a/networksecurity/service/src/com/android/server/net/ct/CertificateTransparencyService.java b/networksecurity/service/src/com/android/server/net/ct/CertificateTransparencyService.java
index edf7c56..ac55e44 100644
--- a/networksecurity/service/src/com/android/server/net/ct/CertificateTransparencyService.java
+++ b/networksecurity/service/src/com/android/server/net/ct/CertificateTransparencyService.java
@@ -28,7 +28,10 @@
 @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
 public class CertificateTransparencyService extends ICertificateTransparencyManager.Stub {
 
+    private final DataStore mDataStore;
+    private final CertificateTransparencyDownloader mCertificateTransparencyDownloader;
     private final CertificateTransparencyFlagsListener mFlagsListener;
+    private final CertificateTransparencyJob mCertificateTransparencyJob;
 
     /**
      * @return true if the CertificateTransparency service is enabled.
@@ -41,7 +44,15 @@
 
     /** Creates a new {@link CertificateTransparencyService} object. */
     public CertificateTransparencyService(Context context) {
-        mFlagsListener = new CertificateTransparencyFlagsListener(context);
+        mDataStore = new DataStore(Config.PREFERENCES_FILE);
+        mCertificateTransparencyDownloader =
+                new CertificateTransparencyDownloader(context, mDataStore);
+        mFlagsListener =
+                new CertificateTransparencyFlagsListener(
+                        mDataStore, mCertificateTransparencyDownloader);
+        mCertificateTransparencyJob =
+                new CertificateTransparencyJob(
+                        context, mDataStore, mCertificateTransparencyDownloader, mFlagsListener);
     }
 
     /**
@@ -53,7 +64,11 @@
 
         switch (phase) {
             case SystemService.PHASE_BOOT_COMPLETED:
-                mFlagsListener.initialize();
+                if (Flags.certificateTransparencyJob()) {
+                    mCertificateTransparencyJob.initialize();
+                } else {
+                    mFlagsListener.initialize();
+                }
                 break;
             default:
         }
diff --git a/thread/TEST_MAPPING b/thread/TEST_MAPPING
index 34d67bb..40842f1 100644
--- a/thread/TEST_MAPPING
+++ b/thread/TEST_MAPPING
@@ -13,6 +13,9 @@
   "postsubmit": [
     {
       "name": "ThreadNetworkMultiDeviceTests"
+    },
+    {
+      "name": "ThreadNetworkTrelDisabledTests"
     }
   ]
 }
diff --git a/thread/tests/integration/Android.bp b/thread/tests/integration/Android.bp
index 8f082a4..798a51e 100644
--- a/thread/tests/integration/Android.bp
+++ b/thread/tests/integration/Android.bp
@@ -62,3 +62,23 @@
     ],
     compile_multilib: "both",
 }
+
+android_test {
+    name: "ThreadNetworkTrelDisabledTests",
+    platform_apis: true,
+    manifest: "AndroidManifest.xml",
+    test_config: "AndroidTestTrelDisabled.xml",
+    defaults: [
+        "framework-connectivity-test-defaults",
+        "ThreadNetworkIntegrationTestsDefaults",
+    ],
+    test_suites: [
+        "mts-tethering",
+        "general-tests",
+    ],
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.kt",
+    ],
+    compile_multilib: "both",
+}
diff --git a/thread/tests/integration/AndroidTestTrelDisabled.xml b/thread/tests/integration/AndroidTestTrelDisabled.xml
new file mode 100644
index 0000000..600652a
--- /dev/null
+++ b/thread/tests/integration/AndroidTestTrelDisabled.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2024 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.
+ -->
+
+<configuration description="Config for Thread integration tests with TREL disabled">
+    <option name="test-tag" value="ThreadNetworkTrelDisabledTests" />
+    <option name="test-suite-tag" value="apct" />
+
+    <!--
+        Only run tests if the device under test is SDK version 34 (Android 14) or above.
+    -->
+    <object type="module_controller"
+            class="com.android.tradefed.testtype.suite.module.Sdk34ModuleController" />
+
+    <!-- Run tests in MTS only if the Tethering Mainline module is installed. -->
+    <object type="module_controller"
+            class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
+        <option name="mainline-module-package-name" value="com.google.android.tethering" />
+    </object>
+
+    <object type="module_controller"
+            class="com.android.tradefed.testtype.suite.module.DeviceFeatureModuleController">
+        <option name="required-feature" value="android.hardware.thread_network" />
+    </object>
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+
+    <!-- Install test -->
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="test-file-name" value="ThreadNetworkTrelDisabledTests.apk" />
+        <option name="check-min-sdk" value="true" />
+        <option name="cleanup-apks" value="true" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.thread.tests.integration" />
+    </test>
+
+    <!-- Disable TREL for integration tests -->
+    <target_preparer class="com.android.tradefed.targetprep.FeatureFlagTargetPreparer">
+        <option name="flag-value"
+                value="thread_network/TrelFeature__enabled=false"/>
+    </target_preparer>
+</configuration>
diff --git a/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java b/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java
index 15259c8..6c2a9bb 100644
--- a/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java
+++ b/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java
@@ -30,6 +30,8 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertThrows;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
@@ -50,6 +52,7 @@
 import androidx.test.filters.LargeTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.net.module.util.DeviceConfigUtils;
 import com.android.net.module.util.HexDump;
 
 import com.google.common.truth.Correspondence;
@@ -445,9 +448,13 @@
     }
 
     @Test
-    // TODO: move this case out to BorderRoutingTest when the service discovery utilities
+    // TODO: move this case out of ServiceDiscoveryTest when the service discovery utilities
     // are decoupled from this test.
     public void trelFeatureFlagEnabled_trelServicePublished() throws Exception {
+        assumeTrue(
+                DeviceConfigUtils.getDeviceConfigPropertyBoolean(
+                        "thread_network", "TrelFeature__enabled", false));
+
         NsdServiceInfo discoveredService = discoverService(mNsdManager, "_trel._udp");
         assertThat(discoveredService).isNotNull();
         // Resolve service with the current TREL port, otherwise it may return stale service from
@@ -463,6 +470,17 @@
                 .isEqualTo(mOtCtl.getExtendedPanId().toLowerCase(Locale.ROOT));
     }
 
+    @Test
+    // TODO: move this case out of ServiceDiscoveryTest when the service discovery utilities
+    // are decoupled from this test.
+    public void trelFeatureFlagDisabled_trelServiceNotPublished() throws Exception {
+        assumeFalse(
+                DeviceConfigUtils.getDeviceConfigPropertyBoolean(
+                        "thread_network", "TrelFeature__enabled", false));
+
+        assertThrows(TimeoutException.class, () -> discoverService(mNsdManager, "_trel._udp"));
+    }
+
     private void registerService(NsdServiceInfo serviceInfo, RegistrationListener listener)
             throws InterruptedException, ExecutionException, TimeoutException {
         mNsdManager.registerService(serviceInfo, PROTOCOL_DNS_SD, listener);