Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e4f57c49 authored by Darrell Shi's avatar Darrell Shi
Browse files

Introduce communal trusted network condition.

This condition, when started, monitors Wi-Fi connections and reports
whether the device is currently connected to a trusted network.

Test: atest CommunalTrustedNetworkConditionTest
Bug: 202778351
Change-Id: Idcc93f9eb73075129ccba9b02b9ccb416ee07aaa
parent bcdaf0ce
Loading
Loading
Loading
Loading
+122 −0
Original line number Diff line number Diff line
/*
 * 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.systemui.communal.conditions;

import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.wifi.WifiInfo;
import android.util.Log;

import androidx.annotation.NonNull;

import javax.inject.Inject;

/**
 * Monitors Wi-Fi connections and triggers callback, if any, when the device is connected to and
 * disconnected from a trusted network.
 */
public class CommunalTrustedNetworkCondition extends CommunalCondition {
    private final String mTag = getClass().getSimpleName();
    private final ConnectivityManager mConnectivityManager;

    @Inject
    public CommunalTrustedNetworkCondition(ConnectivityManager connectivityManager) {
        mConnectivityManager = connectivityManager;
    }

    /**
     * Starts monitoring for trusted network connection. Ignores if already started.
     */
    @Override
    protected void start() {
        if (shouldLog()) Log.d(mTag, "start listening for wifi connections");

        final NetworkRequest wifiNetworkRequest = new NetworkRequest.Builder().addTransportType(
                NetworkCapabilities.TRANSPORT_WIFI).build();
        mConnectivityManager.registerNetworkCallback(wifiNetworkRequest, mNetworkCallback);
    }

    /**
     * Stops monitoring for trusted network connection.
     */
    @Override
    protected void stop() {
        if (shouldLog()) Log.d(mTag, "stop listening for wifi connections");

        mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
    }

    private void updateWifiInfo(WifiInfo wifiInfo) {
        // TODO(b/202778351): check whether wifi is trusted.
        final boolean connectedToTrustedNetwork = wifiInfo != null;

        if (shouldLog()) {
            Log.d(mTag, (connectedToTrustedNetwork ? "connected to" : "disconnected from")
                    + " a trusted network");
        }

        updateCondition(connectedToTrustedNetwork);
    }

    private final ConnectivityManager.NetworkCallback mNetworkCallback =
            new ConnectivityManager.NetworkCallback(
                    ConnectivityManager.NetworkCallback.FLAG_INCLUDE_LOCATION_INFO) {
                private boolean mIsConnected = false;
                private WifiInfo mWifiInfo;

                @Override
                public void onAvailable(@NonNull Network network) {
                    super.onAvailable(network);

                    if (shouldLog()) Log.d(mTag, "connected to wifi");

                    mIsConnected = true;
                    if (mWifiInfo != null) {
                        updateWifiInfo(mWifiInfo);
                    }
                }

                @Override
                public void onLost(@NonNull Network network) {
                    super.onLost(network);

                    if (shouldLog()) Log.d(mTag, "disconnected from wifi");

                    mIsConnected = false;
                    mWifiInfo = null;
                    updateWifiInfo(null);
                }

                @Override
                public void onCapabilitiesChanged(@NonNull Network network,
                        @NonNull NetworkCapabilities networkCapabilities) {
                    super.onCapabilitiesChanged(network, networkCapabilities);

                    mWifiInfo = (WifiInfo) networkCapabilities.getTransportInfo();

                    if (mIsConnected) {
                        updateWifiInfo(mWifiInfo);
                    }
                }
            };

    private boolean shouldLog() {
        return Log.isLoggable(mTag, Log.DEBUG);
    }
}
+6 −3
Original line number Diff line number Diff line
@@ -22,11 +22,12 @@ import android.widget.FrameLayout;

import com.android.systemui.communal.conditions.CommunalCondition;
import com.android.systemui.communal.conditions.CommunalSettingCondition;
import com.android.systemui.communal.conditions.CommunalTrustedNetworkCondition;
import com.android.systemui.idle.AmbientLightModeMonitor;
import com.android.systemui.idle.LightSensorEventsDebounceAlgorithm;
import com.android.systemui.idle.dagger.IdleViewComponent;

import java.util.Collections;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

@@ -72,7 +73,9 @@ public interface CommunalModule {
    @ElementsIntoSet
    @Named(COMMUNAL_CONDITIONS)
    static Set<CommunalCondition> provideCommunalConditions(
            CommunalSettingCondition communalSettingCondition) {
        return new HashSet<>(Collections.singletonList(communalSettingCondition));
            CommunalSettingCondition communalSettingCondition,
            CommunalTrustedNetworkCondition communalTrustedNetworkCondition) {
        return new HashSet<>(
                Arrays.asList(communalSettingCondition, communalTrustedNetworkCondition));
    }
}
+112 −0
Original line number Diff line number Diff line
/*
 * 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.systemui.communal;

import static org.mockito.Mockito.any;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.wifi.WifiInfo;
import android.testing.AndroidTestingRunner;

import androidx.test.filters.SmallTest;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.communal.conditions.CommunalTrustedNetworkCondition;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@SmallTest
@RunWith(AndroidTestingRunner.class)
public class CommunalTrustedNetworkConditionTest extends SysuiTestCase {
    @Mock private ConnectivityManager mConnectivityManager;

    @Captor private ArgumentCaptor<ConnectivityManager.NetworkCallback> mNetworkCallbackCaptor;

    private CommunalTrustedNetworkCondition mCondition;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mCondition = new CommunalTrustedNetworkCondition(mConnectivityManager);
    }

    @Test
    public void updateCallback_connectedToTrustedNetwork_reportsTrue() {
        final CommunalTrustedNetworkCondition.Callback callback =
                mock(CommunalTrustedNetworkCondition.Callback.class);
        mCondition.addCallback(callback);

        final ConnectivityManager.NetworkCallback networkCallback = captureNetworkCallback();

        // Connected to Wi-Fi.
        final Network network = mock(Network.class);
        networkCallback.onAvailable(network);
        networkCallback.onCapabilitiesChanged(network, fakeNetworkCapabilities());

        // Verifies that the callback is triggered.
        verify(callback).onConditionChanged(mCondition, true);
    }

    @Test
    public void updateCallback_disconnectedFromTrustedNetwork_reportsFalse() {
        final CommunalTrustedNetworkCondition.Callback callback =
                mock(CommunalTrustedNetworkCondition.Callback.class);
        mCondition.addCallback(callback);

        final ConnectivityManager.NetworkCallback networkCallback = captureNetworkCallback();

        // Connected to Wi-Fi.
        final Network network = mock(Network.class);
        networkCallback.onAvailable(network);
        networkCallback.onCapabilitiesChanged(network, fakeNetworkCapabilities());
        clearInvocations(callback);

        // Disconnected from Wi-Fi.
        networkCallback.onLost(network);

        // Verifies that the callback is triggered.
        verify(callback).onConditionChanged(mCondition, false);
    }

    // Captures and returns the network callback, assuming it is registered with the connectivity
    // manager.
    private ConnectivityManager.NetworkCallback captureNetworkCallback() {
        verify(mConnectivityManager).registerNetworkCallback(any(NetworkRequest.class),
                mNetworkCallbackCaptor.capture());
        return mNetworkCallbackCaptor.getValue();
    }

    private NetworkCapabilities fakeNetworkCapabilities() {
        final NetworkCapabilities networkCapabilities = mock(NetworkCapabilities.class);
        final WifiInfo wifiInfo = mock(WifiInfo.class);
        when(networkCapabilities.getTransportInfo()).thenReturn(wifiInfo);
        return networkCapabilities;
    }
}