Merge changes I044d0363,I0be3b802,Ib584ea57,I92291023

* changes:
  bpf is required so /sys/fs/bpf/map_netd_app_uid_stats_map always exists
  bpf is required - remove mUseBpfTrafficStats field
  bpf is required - remove checkBpfStatsEnable()
  remove qtaguid parsing
diff --git a/services/core/java/com/android/server/health/HealthRegCallbackAidl.java b/services/core/java/com/android/server/health/HealthRegCallbackAidl.java
new file mode 100644
index 0000000..629011a
--- /dev/null
+++ b/services/core/java/com/android/server/health/HealthRegCallbackAidl.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2021 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.health;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.health.HealthInfo;
+import android.hardware.health.IHealth;
+import android.hardware.health.IHealthInfoCallback;
+import android.os.RemoteException;
+import android.os.Trace;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * On service registration, {@link #onRegistration} is called, which registers {@code this}, an
+ * {@link IHealthInfoCallback}, to the health service.
+ *
+ * <p>When the health service has updates to health info via {@link IHealthInfoCallback}, {@link
+ * HealthInfoCallback#update} is called.
+ *
+ * <p>AIDL variant of {@link HealthHalCallbackHidl}.
+ *
+ * @hide
+ */
+// It is made public so Mockito can access this class. It should have been package private if not
+// for testing.
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public class HealthRegCallbackAidl {
+    private static final String TAG = "HealthRegCallbackAidl";
+    private final HealthInfoCallback mServiceInfoCallback;
+    private final IHealthInfoCallback mHalInfoCallback = new HalInfoCallback();
+
+    HealthRegCallbackAidl(@Nullable HealthInfoCallback healthInfoCallback) {
+        mServiceInfoCallback = healthInfoCallback;
+    }
+
+    /**
+     * Called when the service manager sees {@code newService} replacing {@code oldService}.
+     * This unregisters the health info callback from the old service (ignoring errors), then
+     * registers the health info callback to the new service.
+     *
+     * @param oldService the old IHealth service
+     * @param newService the new IHealth service
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public void onRegistration(@Nullable IHealth oldService, @NonNull IHealth newService) {
+        if (mServiceInfoCallback == null) return;
+
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "HealthUnregisterCallbackAidl");
+        try {
+            unregisterCallback(oldService, mHalInfoCallback);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+        }
+
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "HealthRegisterCallbackAidl");
+        try {
+            registerCallback(newService, mHalInfoCallback);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+        }
+    }
+
+    private static void unregisterCallback(@Nullable IHealth oldService, IHealthInfoCallback cb) {
+        if (oldService == null) return;
+        try {
+            oldService.unregisterCallback(cb);
+        } catch (RemoteException e) {
+            // Ignore errors. The service might have died.
+            Slog.w(
+                    TAG,
+                    "health: cannot unregister previous callback (transaction error): "
+                            + e.getMessage());
+        }
+    }
+
+    private static void registerCallback(@NonNull IHealth newService, IHealthInfoCallback cb) {
+        try {
+            newService.registerCallback(cb);
+        } catch (RemoteException e) {
+            Slog.e(
+                    TAG,
+                    "health: cannot register callback, framework may cease to"
+                            + " receive updates on health / battery info!",
+                    e);
+            return;
+        }
+        // registerCallback does NOT guarantee that update is called immediately, so request a
+        // manual update here.
+        try {
+            newService.update();
+        } catch (RemoteException e) {
+            Slog.e(TAG, "health: cannot update after registering health info callback", e);
+        }
+    }
+
+    private class HalInfoCallback extends IHealthInfoCallback.Stub {
+        @Override
+        public void healthInfoChanged(HealthInfo healthInfo) throws RemoteException {
+            mServiceInfoCallback.update(healthInfo);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/health/HealthServiceWrapper.java b/services/core/java/com/android/server/health/HealthServiceWrapper.java
index 9b97554..25d1a88 100644
--- a/services/core/java/com/android/server/health/HealthServiceWrapper.java
+++ b/services/core/java/com/android/server/health/HealthServiceWrapper.java
@@ -81,6 +81,8 @@
     public static HealthServiceWrapper create(@Nullable HealthInfoCallback healthInfoCallback)
             throws RemoteException, NoSuchElementException {
         return create(
+                healthInfoCallback == null ? null : new HealthRegCallbackAidl(healthInfoCallback),
+                new HealthServiceWrapperAidl.ServiceManagerStub() {},
                 healthInfoCallback == null ? null : new HealthHalCallbackHidl(healthInfoCallback),
                 new HealthServiceWrapperHidl.IServiceManagerSupplier() {},
                 new HealthServiceWrapperHidl.IHealthSupplier() {});
@@ -89,6 +91,9 @@
     /**
      * Create a new HealthServiceWrapper instance for testing.
      *
+     * @param aidlRegCallback callback for AIDL service registration, or {@code null} if the client
+     *     does not care about AIDL service registration notifications
+     * @param aidlServiceManager Stub for AIDL ServiceManager
      * @param hidlRegCallback callback for HIDL service registration, or {@code null} if the client
      *     does not care about HIDL service registration notifications
      * @param hidlServiceManagerSupplier supplier of HIDL service manager
@@ -97,10 +102,17 @@
      */
     @VisibleForTesting
     static @NonNull HealthServiceWrapper create(
+            @Nullable HealthRegCallbackAidl aidlRegCallback,
+            @NonNull HealthServiceWrapperAidl.ServiceManagerStub aidlServiceManager,
             @Nullable HealthServiceWrapperHidl.Callback hidlRegCallback,
             @NonNull HealthServiceWrapperHidl.IServiceManagerSupplier hidlServiceManagerSupplier,
             @NonNull HealthServiceWrapperHidl.IHealthSupplier hidlHealthSupplier)
             throws RemoteException, NoSuchElementException {
+        try {
+            return new HealthServiceWrapperAidl(aidlRegCallback, aidlServiceManager);
+        } catch (NoSuchElementException e) {
+            // Ignore, try HIDL
+        }
         return new HealthServiceWrapperHidl(
                 hidlRegCallback, hidlServiceManagerSupplier, hidlHealthSupplier);
     }
diff --git a/services/core/java/com/android/server/health/HealthServiceWrapperAidl.java b/services/core/java/com/android/server/health/HealthServiceWrapperAidl.java
new file mode 100644
index 0000000..4f2ed68
--- /dev/null
+++ b/services/core/java/com/android/server/health/HealthServiceWrapperAidl.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2021 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.health;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.health.HealthInfo;
+import android.hardware.health.IHealth;
+import android.os.BatteryManager;
+import android.os.BatteryProperty;
+import android.os.Binder;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.IServiceCallback;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
+import android.os.Trace;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Implement {@link HealthServiceWrapper} backed by the AIDL HAL.
+ *
+ * @hide
+ */
+class HealthServiceWrapperAidl extends HealthServiceWrapper {
+    private static final String TAG = "HealthServiceWrapperAidl";
+    @VisibleForTesting static final String SERVICE_NAME = IHealth.DESCRIPTOR + "/default";
+    private final HandlerThread mHandlerThread = new HandlerThread("HealthServiceBinder");
+    private final AtomicReference<IHealth> mLastService = new AtomicReference<>();
+    private final IServiceCallback mServiceCallback = new ServiceCallback();
+    private final HealthRegCallbackAidl mRegCallback;
+
+    /** Stub interface into {@link ServiceManager} for testing. */
+    interface ServiceManagerStub {
+        default @Nullable IHealth waitForDeclaredService(@NonNull String name) {
+            return IHealth.Stub.asInterface(ServiceManager.waitForDeclaredService(name));
+        }
+
+        default void registerForNotifications(
+                @NonNull String name, @NonNull IServiceCallback callback) throws RemoteException {
+            ServiceManager.registerForNotifications(name, callback);
+        }
+    }
+
+    HealthServiceWrapperAidl(
+            @Nullable HealthRegCallbackAidl regCallback, @NonNull ServiceManagerStub serviceManager)
+            throws RemoteException, NoSuchElementException {
+
+        traceBegin("HealthInitGetServiceAidl");
+        IHealth newService;
+        try {
+            newService = serviceManager.waitForDeclaredService(SERVICE_NAME);
+        } finally {
+            traceEnd();
+        }
+        if (newService == null) {
+            throw new NoSuchElementException(
+                    "IHealth service instance isn't available. Perhaps no permission?");
+        }
+        mLastService.set(newService);
+        mRegCallback = regCallback;
+        if (mRegCallback != null) {
+            mRegCallback.onRegistration(null /* oldService */, newService);
+        }
+
+        traceBegin("HealthInitRegisterNotificationAidl");
+        mHandlerThread.start();
+        try {
+            serviceManager.registerForNotifications(SERVICE_NAME, mServiceCallback);
+        } finally {
+            traceEnd();
+        }
+        Slog.i(TAG, "health: HealthServiceWrapper listening to AIDL HAL");
+    }
+
+    @Override
+    @VisibleForTesting
+    public HandlerThread getHandlerThread() {
+        return mHandlerThread;
+    }
+
+    @Override
+    public int getProperty(int id, BatteryProperty prop) throws RemoteException {
+        traceBegin("HealthGetPropertyAidl");
+        try {
+            return getPropertyInternal(id, prop);
+        } finally {
+            traceEnd();
+        }
+    }
+
+    private int getPropertyInternal(int id, BatteryProperty prop) throws RemoteException {
+        IHealth service = mLastService.get();
+        if (service == null) throw new RemoteException("no health service");
+        try {
+            switch (id) {
+                case BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER:
+                    prop.setLong(service.getChargeCounterUah());
+                    break;
+                case BatteryManager.BATTERY_PROPERTY_CURRENT_NOW:
+                    prop.setLong(service.getCurrentNowMicroamps());
+                    break;
+                case BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE:
+                    prop.setLong(service.getCurrentAverageMicroamps());
+                    break;
+                case BatteryManager.BATTERY_PROPERTY_CAPACITY:
+                    prop.setLong(service.getCapacity());
+                    break;
+                case BatteryManager.BATTERY_PROPERTY_STATUS:
+                    prop.setLong(service.getChargeStatus());
+                    break;
+                case BatteryManager.BATTERY_PROPERTY_ENERGY_COUNTER:
+                    prop.setLong(service.getEnergyCounterNwh());
+                    break;
+            }
+        } catch (UnsupportedOperationException e) {
+            // Leave prop untouched.
+            return -1;
+        } catch (ServiceSpecificException e) {
+            // Leave prop untouched.
+            return -2;
+        }
+        // throws RemoteException as-is. BatteryManager wraps it into a RuntimeException
+        // and throw it to apps.
+
+        // If no error, return 0.
+        return 0;
+    }
+
+    @Override
+    public void scheduleUpdate() throws RemoteException {
+        getHandlerThread()
+                .getThreadHandler()
+                .post(
+                        () -> {
+                            traceBegin("HealthScheduleUpdate");
+                            try {
+                                IHealth service = mLastService.get();
+                                if (service == null) {
+                                    Slog.e(TAG, "no health service");
+                                    return;
+                                }
+                                service.update();
+                            } catch (RemoteException | ServiceSpecificException ex) {
+                                Slog.e(TAG, "Cannot call update on health AIDL HAL", ex);
+                            } finally {
+                                traceEnd();
+                            }
+                        });
+    }
+
+    @Override
+    public HealthInfo getHealthInfo() throws RemoteException {
+        IHealth service = mLastService.get();
+        if (service == null) return null;
+        try {
+            return service.getHealthInfo();
+        } catch (UnsupportedOperationException | ServiceSpecificException ex) {
+            return null;
+        }
+    }
+
+    private static void traceBegin(String name) {
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, name);
+    }
+
+    private static void traceEnd() {
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+    }
+
+    private class ServiceCallback extends IServiceCallback.Stub {
+        @Override
+        public void onRegistration(String name, @NonNull final IBinder newBinder)
+                throws RemoteException {
+            if (!SERVICE_NAME.equals(name)) return;
+            // This runnable only runs on mHandlerThread and ordering is ensured, hence
+            // no locking is needed inside the runnable.
+            getHandlerThread()
+                    .getThreadHandler()
+                    .post(
+                            () -> {
+                                IHealth newService =
+                                        IHealth.Stub.asInterface(Binder.allowBlocking(newBinder));
+                                IHealth oldService = mLastService.getAndSet(newService);
+                                IBinder oldBinder =
+                                        oldService != null ? oldService.asBinder() : null;
+                                if (Objects.equals(newBinder, oldBinder)) return;
+
+                                Slog.i(TAG, "New health AIDL HAL service registered");
+                                mRegCallback.onRegistration(oldService, newService);
+                            });
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/health/HealthServiceWrapperTest.java b/services/tests/servicestests/src/com/android/server/health/HealthServiceWrapperTest.java
index c97a67b..16d97a4 100644
--- a/services/tests/servicestests/src/com/android/server/health/HealthServiceWrapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/health/HealthServiceWrapperTest.java
@@ -19,11 +19,12 @@
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.fail;
 
+import static org.mockito.AdditionalMatchers.not;
 import static org.mockito.Mockito.*;
 
-import android.hardware.health.V2_0.IHealth;
 import android.hidl.manager.V1_0.IServiceManager;
 import android.hidl.manager.V1_0.IServiceNotification;
+import android.os.IServiceCallback;
 import android.os.RemoteException;
 
 import androidx.test.filters.SmallTest;
@@ -44,28 +45,47 @@
 
 @RunWith(AndroidJUnit4.class)
 public class HealthServiceWrapperTest {
-
     @Mock IServiceManager mMockedManager;
-    @Mock IHealth mMockedHal;
-    @Mock IHealth mMockedHal2;
+    @Mock android.hardware.health.V2_0.IHealth mMockedHal;
+    @Mock android.hardware.health.V2_0.IHealth mMockedHal2;
 
     @Mock HealthServiceWrapperHidl.Callback mCallback;
     @Mock HealthServiceWrapperHidl.IServiceManagerSupplier mManagerSupplier;
     @Mock HealthServiceWrapperHidl.IHealthSupplier mHealthServiceSupplier;
+
+    @Mock android.hardware.health.IHealth.Stub mMockedAidlHal;
+    @Mock android.hardware.health.IHealth.Stub mMockedAidlHal2;
+    @Mock HealthServiceWrapperAidl.ServiceManagerStub mMockedAidlManager;
+    @Mock HealthRegCallbackAidl mRegCallbackAidl;
+
     HealthServiceWrapper mWrapper;
 
     private static final String VENDOR = HealthServiceWrapperHidl.INSTANCE_VENDOR;
+    private static final String AIDL_SERVICE_NAME = HealthServiceWrapperAidl.SERVICE_NAME;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+
+        // Mocks the conversion between IHealth and IBinder.
+        when(mMockedAidlHal.asBinder()).thenCallRealMethod(); // returns mMockedAidlHal
+        when(mMockedAidlHal2.asBinder()).thenCallRealMethod(); // returns mMockedAidlHal2
+        when(mMockedAidlHal.queryLocalInterface(android.hardware.health.IHealth.DESCRIPTOR))
+                .thenReturn(mMockedAidlHal);
+        when(mMockedAidlHal2.queryLocalInterface(android.hardware.health.IHealth.DESCRIPTOR))
+                .thenReturn(mMockedAidlHal2);
     }
 
     @After
     public void tearDown() {
+        validateMockitoUsage();
         if (mWrapper != null) mWrapper.getHandlerThread().quitSafely();
     }
 
+    public static <T> ArgumentMatcher<T> isOneOf(T[] collection) {
+        return isOneOf(Arrays.asList(collection));
+    }
+
     public static <T> ArgumentMatcher<T> isOneOf(Collection<T> collection) {
         return new ArgumentMatcher<T>() {
             @Override
@@ -75,13 +95,39 @@
 
             @Override
             public String toString() {
-                return collection.toString();
+                return "is one of " + collection.toString();
             }
         };
     }
 
-    private void initForInstances(String... instanceNamesArr) throws Exception {
-        final Collection<String> instanceNames = Arrays.asList(instanceNamesArr);
+    /**
+     * Set up mock objects to pretend that the given AIDL and HIDL instances exists.
+     *
+     * <p>Also, when registering service notifications, the mocked service managers immediately
+     * sends 3 registration notifications, including 2 referring to the original HAL and 1 referring
+     * to the new HAL.
+     *
+     * @param aidlInstances e.g. {"android.hardware.health.IHealth/default"}
+     * @param hidlInstances e.g. {"default", "backup"}
+     * @throws Exception
+     */
+    private void initForInstances(String[] aidlInstances, String[] hidlInstances) throws Exception {
+        doAnswer(
+                (invocation) -> {
+                    sendAidlRegCallback(invocation, mMockedAidlHal);
+                    sendAidlRegCallback(invocation, mMockedAidlHal);
+                    sendAidlRegCallback(invocation, mMockedAidlHal2);
+                    return null;
+                })
+                .when(mMockedAidlManager)
+                .registerForNotifications(
+                        argThat(isOneOf(aidlInstances)), any(IServiceCallback.class));
+        when(mMockedAidlManager.waitForDeclaredService(argThat(isOneOf(aidlInstances))))
+                .thenReturn(mMockedAidlHal)
+                .thenThrow(new RuntimeException("waitForDeclaredService called more than once"));
+        when(mMockedAidlManager.waitForDeclaredService(not(argThat(isOneOf(aidlInstances)))))
+                .thenReturn(null);
+
         doAnswer(
                 (invocation) -> {
                     // technically, preexisting is ignored by
@@ -93,8 +139,8 @@
                 })
                 .when(mMockedManager)
                 .registerForNotifications(
-                        eq(IHealth.kInterfaceName),
-                        argThat(isOneOf(instanceNames)),
+                        eq(android.hardware.health.V2_0.IHealth.kInterfaceName),
+                        argThat(isOneOf(hidlInstances)),
                         any(IServiceNotification.class));
 
         doReturn(mMockedManager).when(mManagerSupplier).get();
@@ -104,7 +150,7 @@
                 .doReturn(mMockedHal2) // notification 3
                 .doThrow(new RuntimeException("Should not call getService for more than 4 times"))
                 .when(mHealthServiceSupplier)
-                .get(argThat(isOneOf(instanceNames)));
+                .get(argThat(isOneOf(hidlInstances)));
     }
 
     private void waitHandlerThreadFinish() throws Exception {
@@ -121,19 +167,62 @@
             throws Exception {
         ((IServiceNotification) invocation.getArguments()[2])
                 .onRegistration(
-                        IHealth.kInterfaceName, (String) invocation.getArguments()[1], preexisting);
+                        android.hardware.health.V2_0.IHealth.kInterfaceName,
+                        (String) invocation.getArguments()[1],
+                        preexisting);
+    }
+
+    private static void sendAidlRegCallback(
+            InvocationOnMock invocation, android.hardware.health.IHealth service) throws Exception {
+        ((IServiceCallback) invocation.getArguments()[1])
+                .onRegistration((String) invocation.getArguments()[0], service.asBinder());
     }
 
     private void createWrapper() throws RemoteException {
-        mWrapper = HealthServiceWrapper.create(mCallback, mManagerSupplier, mHealthServiceSupplier);
+        mWrapper =
+                HealthServiceWrapper.create(
+                        mRegCallbackAidl,
+                        mMockedAidlManager,
+                        mCallback,
+                        mManagerSupplier,
+                        mHealthServiceSupplier);
     }
 
     @SmallTest
     @Test
-    public void testWrapPreferVendor() throws Exception {
-        initForInstances(VENDOR);
+    public void testWrapAidlOnly() throws Exception {
+        initForInstances(new String[] {AIDL_SERVICE_NAME}, new String[0]);
         createWrapper();
         waitHandlerThreadFinish();
+        verify(mRegCallbackAidl, times(1)).onRegistration(same(null), same(mMockedAidlHal));
+        verify(mRegCallbackAidl, never())
+                .onRegistration(same(mMockedAidlHal), same(mMockedAidlHal));
+        verify(mRegCallbackAidl, times(1))
+                .onRegistration(same(mMockedAidlHal), same(mMockedAidlHal2));
+        verify(mCallback, never()).onRegistration(any(), any(), anyString());
+    }
+
+    @SmallTest
+    @Test
+    public void testWrapPreferAidl() throws Exception {
+        initForInstances(new String[] {AIDL_SERVICE_NAME}, new String[] {VENDOR});
+        createWrapper();
+        waitHandlerThreadFinish();
+        verify(mRegCallbackAidl, times(1)).onRegistration(same(null), same(mMockedAidlHal));
+        verify(mRegCallbackAidl, never())
+                .onRegistration(same(mMockedAidlHal), same(mMockedAidlHal));
+        verify(mRegCallbackAidl, times(1))
+                .onRegistration(same(mMockedAidlHal), same(mMockedAidlHal2));
+        verify(mCallback, never()).onRegistration(any(), any(), anyString());
+    }
+
+    @SmallTest
+    @Test
+    public void testWrapFallbackHidl() throws Exception {
+        initForInstances(new String[0], new String[] {VENDOR});
+        createWrapper();
+        waitHandlerThreadFinish();
+        verify(mRegCallbackAidl, never()).onRegistration(any(), any());
         verify(mCallback, times(1)).onRegistration(same(null), same(mMockedHal), eq(VENDOR));
         verify(mCallback, never()).onRegistration(same(mMockedHal), same(mMockedHal), anyString());
         verify(mCallback, times(1)).onRegistration(same(mMockedHal), same(mMockedHal2), eq(VENDOR));
@@ -142,7 +231,7 @@
     @SmallTest
     @Test
     public void testNoService() throws Exception {
-        initForInstances("unrelated");
+        initForInstances(new String[0], new String[] {"unrelated"});
         try {
             createWrapper();
             fail("Expect NoSuchElementException");