1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.vpn2; 18 19 import android.app.Dialog; 20 import android.app.admin.DevicePolicyManager; 21 import android.app.settings.SettingsEnums; 22 import android.content.DialogInterface; 23 import android.content.pm.PackageInfo; 24 import android.net.VpnManager; 25 import android.os.Bundle; 26 import android.os.UserHandle; 27 import android.os.UserManager; 28 29 import androidx.appcompat.app.AlertDialog; 30 import androidx.fragment.app.Fragment; 31 32 import com.android.internal.net.VpnConfig; 33 import com.android.settings.R; 34 import com.android.settings.core.instrumentation.InstrumentedDialogFragment; 35 36 /** 37 * Fragment wrapper around an {@link AppDialog}. 38 */ 39 public class AppDialogFragment extends InstrumentedDialogFragment implements AppDialog.Listener { 40 private static final String TAG_APP_DIALOG = "vpnappdialog"; 41 private static final String TAG = "AppDialogFragment"; 42 43 private static final String ARG_MANAGING = "managing"; 44 private static final String ARG_LABEL = "label"; 45 private static final String ARG_CONNECTED = "connected"; 46 private static final String ARG_PACKAGE = "package"; 47 48 private PackageInfo mPackageInfo; 49 private Listener mListener; 50 51 private UserManager mUserManager; 52 private DevicePolicyManager mDevicePolicyManager; 53 private VpnManager mVpnManager; 54 55 @Override getMetricsCategory()56 public int getMetricsCategory() { 57 return SettingsEnums.DIALOG_VPN_APP_CONFIG; 58 } 59 60 public interface Listener { onForget()61 void onForget(); onCancel()62 void onCancel(); 63 } 64 show(Fragment parent, PackageInfo packageInfo, String label, boolean managing, boolean connected)65 public static void show(Fragment parent, PackageInfo packageInfo, String label, 66 boolean managing, boolean connected) { 67 if (!managing && !connected) { 68 // We can't display anything useful for this case. 69 return; 70 } 71 show(parent, null, packageInfo, label, managing, connected); 72 } 73 show(Fragment parent, Listener listener, PackageInfo packageInfo, String label, boolean managing, boolean connected)74 public static void show(Fragment parent, Listener listener, PackageInfo packageInfo, 75 String label, boolean managing, boolean connected) { 76 if (!parent.isAdded()) { 77 return; 78 } 79 80 Bundle args = new Bundle(); 81 args.putParcelable(ARG_PACKAGE, packageInfo); 82 args.putString(ARG_LABEL, label); 83 args.putBoolean(ARG_MANAGING, managing); 84 args.putBoolean(ARG_CONNECTED, connected); 85 86 final AppDialogFragment frag = new AppDialogFragment(); 87 frag.mListener = listener; 88 frag.setArguments(args); 89 frag.setTargetFragment(parent, 0); 90 frag.show(parent.getFragmentManager(), TAG_APP_DIALOG); 91 } 92 93 @Override onCreate(Bundle savedInstanceState)94 public void onCreate(Bundle savedInstanceState) { 95 super.onCreate(savedInstanceState); 96 mPackageInfo = getArguments().getParcelable(ARG_PACKAGE); 97 mUserManager = UserManager.get(getContext()); 98 mDevicePolicyManager = getContext() 99 .createContextAsUser(UserHandle.of(getUserId()), /* flags= */ 0) 100 .getSystemService(DevicePolicyManager.class); 101 mVpnManager = getContext().getSystemService(VpnManager.class); 102 } 103 104 @Override onCreateDialog(Bundle savedInstanceState)105 public Dialog onCreateDialog(Bundle savedInstanceState) { 106 Bundle args = getArguments(); 107 final String label = args.getString(ARG_LABEL); 108 boolean managing = args.getBoolean(ARG_MANAGING); 109 boolean connected = args.getBoolean(ARG_CONNECTED); 110 111 if (managing) { 112 return new AppDialog(getActivity(), this, mPackageInfo, label); 113 } else { 114 // Build an AlertDialog with an option to disconnect. 115 AlertDialog.Builder dlog = new AlertDialog.Builder(getActivity()) 116 .setTitle(label) 117 .setMessage(getActivity().getString(R.string.vpn_disconnect_confirm)) 118 .setNegativeButton(getActivity().getString(R.string.vpn_cancel), null); 119 120 if (connected && !isUiRestricted()) { 121 dlog.setPositiveButton(getActivity().getString(R.string.vpn_disconnect), 122 new DialogInterface.OnClickListener() { 123 @Override 124 public void onClick(DialogInterface dialog, int which) { 125 onDisconnect(dialog); 126 } 127 }); 128 } 129 return dlog.create(); 130 } 131 } 132 133 @Override onCancel(DialogInterface dialog)134 public void onCancel(DialogInterface dialog) { 135 dismiss(); 136 if (mListener != null) { 137 mListener.onCancel(); 138 } 139 super.onCancel(dialog); 140 } 141 142 @Override onForget(final DialogInterface dialog)143 public void onForget(final DialogInterface dialog) { 144 if (isUiRestricted()) { 145 return; 146 } 147 final int userId = getUserId(); 148 mVpnManager.setVpnPackageAuthorization( 149 mPackageInfo.packageName, userId, VpnManager.TYPE_VPN_NONE); 150 onDisconnect(dialog); 151 152 if (mListener != null) { 153 mListener.onForget(); 154 } 155 } 156 onDisconnect(final DialogInterface dialog)157 private void onDisconnect(final DialogInterface dialog) { 158 if (isUiRestricted()) { 159 return; 160 } 161 final int userId = getUserId(); 162 if (mPackageInfo.packageName.equals(VpnUtils.getConnectedPackage(mVpnManager, userId))) { 163 mVpnManager.setAlwaysOnVpnPackageForUser(userId, null, /* lockdownEnabled */ false, 164 /* lockdownAllowlist */ null); 165 mVpnManager.prepareVpn(mPackageInfo.packageName, VpnConfig.LEGACY_VPN, userId); 166 } 167 } 168 isUiRestricted()169 private boolean isUiRestricted() { 170 final UserHandle userHandle = UserHandle.of(getUserId()); 171 if (mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, userHandle)) { 172 return true; 173 } 174 return mPackageInfo.packageName.equals(mDevicePolicyManager.getAlwaysOnVpnPackage()); 175 } 176 getUserId()177 private int getUserId() { 178 return UserHandle.getUserId(mPackageInfo.applicationInfo.uid); 179 } 180 } 181