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

Commit 23fe400c authored by Ray Chen's avatar Ray Chen Committed by Automerger Merge Worker
Browse files

Merge changes from topic "VPN_ICON" into main am: 782c1fd1

parents 26ce6c15 782c1fd1
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
**
** Copyright 2023, 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.
*/
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="17dp"
    android:height="17dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path
        android:fillColor="#FFFFFFFF"
        android:pathData="M12.09,9C11.11,7.5 9.43,6.5 7.5,6.5C4.46,6.5 2,8.96 2,12c0,3.04 2.46,5.5 5.5,5.5c1.93,0 3.61,-1 4.59,-2.5H14v3h4V9H12.09zM18,13hv3h-2v-3h-5.16c-0.43,1.44 -1.76,2.5 -3.34,2.5C5.57,15.5 4,13.93 4,12c0,-1.93 1.57,-3.5 3.5,-3.5c1.58,0 2.9,1.06 3.34,2.5H18V13z"/>
    <path
        android:fillColor="#FFFFFFFF"
        android:pathData="M7.5,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
    <path
        android:fillColor="#FFFFFFFF"
        android:pathData="M22,10h-2v8h2V10z"/>
    <path
        android:fillColor="#FFFFFFFF"
        android:pathData="M22,20h-2v2h2V20z"/>
</vector>
+36 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
**
** Copyright 2023, 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.
*/
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="17dp"
    android:height="17dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path
        android:fillColor="#FFFFFFFF"
        android:pathData="M12.09,9C11.11,7.5 9.43,6.5 7.5,6.5C4.46,6.5 2,8.96 2,12c0,3.04 2.46,5.5 5.5,5.5c1.93,0 3.61,-1 4.59,-2.5H14v3h4V9H12.09zM18,13hv3h-2v-3h-5.16c-0.43,1.44 -1.76,2.5 -3.34,2.5C5.57,15.5 4,13.93 4,12c0,-1.93 1.57,-3.5 3.5,-3.5c1.58,0 2.9,1.06 3.34,2.5H18V13z"/>
    <path
        android:fillColor="#FFFFFFFF"
        android:pathData="M7.5,12m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
    <path
        android:fillColor="#FFFFFFFF"
        android:pathData="M22,10h-2v8h2V10z"/>
    <path
        android:fillColor="#FFFFFFFF"
        android:pathData="M22,20h-2v2h2V20z"/>
</vector>
+13 −3
Original line number Diff line number Diff line
@@ -118,15 +118,25 @@ public class StatusBarSignalPolicy implements SignalCallback,

    private void updateVpn() {
        boolean vpnVisible = mSecurityController.isVpnEnabled();
        int vpnIconId = currentVpnIconId(mSecurityController.isVpnBranded());
        int vpnIconId = currentVpnIconId(
                mSecurityController.isVpnBranded(),
                mSecurityController.isVpnValidated());

        mIconController.setIcon(mSlotVpn, vpnIconId,
                mContext.getResources().getString(R.string.accessibility_vpn_on));
        mIconController.setIconVisibility(mSlotVpn, vpnVisible);
    }

    private int currentVpnIconId(boolean isBranded) {
        return isBranded ? R.drawable.stat_sys_branded_vpn : R.drawable.stat_sys_vpn_ic;
    private int currentVpnIconId(boolean isBranded, boolean isValidated) {
        if (isBranded) {
            return isValidated
                    ? R.drawable.stat_sys_branded_vpn
                    : R.drawable.stat_sys_no_internet_branded_vpn;
        } else {
            return isValidated
                    ? R.drawable.stat_sys_vpn_ic
                    : R.drawable.stat_sys_no_internet_vpn_ic;
        }
    }

    /**
+2 −0
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ public interface SecurityController extends CallbackController<SecurityControlle
    boolean isNetworkLoggingEnabled();
    boolean isVpnEnabled();
    boolean isVpnRestricted();
    /** Whether the VPN network is validated. */
    boolean isVpnValidated();
    /** Whether the VPN app should use branded VPN iconography.  */
    boolean isVpnBranded();
    String getPrimaryVpnName();
+122 −1
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
 */
package com.android.systemui.statusbar.policy;

import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;

import android.annotation.Nullable;
import android.app.admin.DeviceAdminInfo;
import android.app.admin.DevicePolicyManager;
@@ -32,7 +35,9 @@ import android.content.pm.UserInfo;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.VpnManager;
import android.os.Handler;
@@ -76,7 +81,10 @@ public class SecurityControllerImpl implements SecurityController {
    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

    private static final NetworkRequest REQUEST =
            new NetworkRequest.Builder().clearCapabilities().build();
            new NetworkRequest.Builder()
                    .clearCapabilities()
                    .addTransportType(TRANSPORT_VPN)
                    .build();
    private static final int NO_NETWORK = -1;

    private static final String VPN_BRANDED_META_DATA = "com.android.systemui.IS_BRANDED";
@@ -99,6 +107,8 @@ public class SecurityControllerImpl implements SecurityController {
    private SparseArray<VpnConfig> mCurrentVpns = new SparseArray<>();
    private int mCurrentUserId;
    private int mVpnUserId;
    @GuardedBy("mNetworkProperties")
    private final SparseArray<NetworkProperties> mNetworkProperties = new SparseArray<>();

    // Key: userId, Value: whether the user has CACerts installed
    // Needs to be cached here since the query has to be asynchronous
@@ -162,6 +172,21 @@ public class SecurityControllerImpl implements SecurityController {
            pw.print(mCurrentVpns.valueAt(i).user);
        }
        pw.println("}");
        pw.print("  mNetworkProperties={");
        synchronized (mNetworkProperties) {
            for (int i = 0; i < mNetworkProperties.size(); ++i) {
                if (i > 0) {
                    pw.print(", ");
                }
                pw.print(mNetworkProperties.keyAt(i));
                pw.print("={");
                pw.print(mNetworkProperties.valueAt(i).interfaceName);
                pw.print(", ");
                pw.print(mNetworkProperties.valueAt(i).validated);
                pw.print("}");
            }
        }
        pw.println("}");
    }

    @Override
@@ -303,6 +328,26 @@ public class SecurityControllerImpl implements SecurityController {
        return isVpnPackageBranded(packageName);
    }

    @Override
    public boolean isVpnValidated() {
        // Prioritize reporting the network status of the parent user.
        final VpnConfig primaryVpnConfig = mCurrentVpns.get(mVpnUserId);
        if (primaryVpnConfig != null) {
            return getVpnValidationStatus(primaryVpnConfig);
        }
        // Identify any Unvalidated status in each active VPN network within other profiles.
        for (int profileId : mUserManager.getEnabledProfileIds(mVpnUserId)) {
            final VpnConfig vpnConfig = mCurrentVpns.get(profileId);
            if (vpnConfig == null) {
                continue;
            }
            if (!getVpnValidationStatus(vpnConfig)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public boolean hasCACertInCurrentUser() {
        Boolean hasCACerts = mHasCACerts.get(mCurrentUserId);
@@ -491,11 +536,74 @@ public class SecurityControllerImpl implements SecurityController {
        @Override
        public void onLost(Network network) {
            if (DEBUG) Log.d(TAG, "onLost " + network.getNetId());
            synchronized (mNetworkProperties) {
                mNetworkProperties.delete(network.getNetId());
            }
            updateState();
            fireCallbacks();
        };


        @Override
        public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
            if (DEBUG) Log.d(TAG, "onCapabilitiesChanged " + network.getNetId());
            final NetworkProperties properties;
            synchronized (mNetworkProperties) {
                properties = mNetworkProperties.get(network.getNetId());
            }
            // When a new network appears, the system first notifies the application about
            // its capabilities through onCapabilitiesChanged. This initial notification
            // will be skipped because the interface information is included in the
            // subsequent onLinkPropertiesChanged call. After validating the network, the
            // system might send another onCapabilitiesChanged notification if the network
            // becomes validated.
            if (properties == null) {
                return;
            }
            final boolean validated = nc.hasCapability(NET_CAPABILITY_VALIDATED);
            if (properties.validated != validated) {
                properties.validated = validated;
                fireCallbacks();
            }
        }

        @Override
        public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
            if (DEBUG) Log.d(TAG, "onLinkPropertiesChanged " + network.getNetId());
            final String interfaceName = linkProperties.getInterfaceName();
            if (interfaceName == null) {
                Log.w(TAG, "onLinkPropertiesChanged event with null interface");
                return;
            }
            synchronized (mNetworkProperties) {
                final NetworkProperties properties = mNetworkProperties.get(network.getNetId());
                if (properties == null) {
                    mNetworkProperties.put(
                            network.getNetId(),
                            new NetworkProperties(interfaceName, false));
                } else {
                    properties.interfaceName = interfaceName;
                }
            }
        }
    };

    /**
     *  Retrieve the validation status of the VPN network associated with the given VpnConfig.
     */
    private boolean getVpnValidationStatus(@NonNull VpnConfig vpnConfig) {
        synchronized (mNetworkProperties) {
            // Find the network has the same interface as the VpnConfig
            for (int i = 0; i < mNetworkProperties.size(); ++i) {
                if (mNetworkProperties.valueAt(i).interfaceName.equals(vpnConfig.interfaze)) {
                    return mNetworkProperties.valueAt(i).validated;
                }
            }
        }
        // If no matching network is found, consider it validated.
        return true;
    }

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override public void onReceive(Context context, Intent intent) {
            if (KeyChain.ACTION_TRUST_STORE_CHANGED.equals(intent.getAction())) {
@@ -506,4 +614,17 @@ public class SecurityControllerImpl implements SecurityController {
            }
        }
    };

    /**
     *  A data class to hold specific Network properties received through the NetworkCallback.
     */
    private static class NetworkProperties {
        public String interfaceName;
        public boolean validated;

        NetworkProperties(@NonNull String interfaceName, boolean validated) {
            this.interfaceName = interfaceName;
            this.validated = validated;
        }
    }
}
Loading