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.settings.SettingsEnums; 21 import android.content.Context; 22 import android.content.DialogInterface; 23 import android.content.pm.PackageInfo; 24 import android.net.IConnectivityManager; 25 import android.os.Bundle; 26 import android.os.RemoteException; 27 import android.os.ServiceManager; 28 import android.os.UserHandle; 29 import android.os.UserManager; 30 import android.util.Log; 31 32 import androidx.appcompat.app.AlertDialog; 33 import androidx.fragment.app.Fragment; 34 35 import com.android.internal.net.VpnConfig; 36 import com.android.settings.R; 37 import com.android.settings.core.instrumentation.InstrumentedDialogFragment; 38 39 /** 40 * Fragment wrapper around an {@link AppDialog}. 41 */ 42 public class AppDialogFragment extends InstrumentedDialogFragment implements AppDialog.Listener { 43 private static final String TAG_APP_DIALOG = "vpnappdialog"; 44 private static final String TAG = "AppDialogFragment"; 45 46 private static final String ARG_MANAGING = "managing"; 47 private static final String ARG_LABEL = "label"; 48 private static final String ARG_CONNECTED = "connected"; 49 private static final String ARG_PACKAGE = "package"; 50 51 private PackageInfo mPackageInfo; 52 private Listener mListener; 53 54 private UserManager mUserManager; 55 private final IConnectivityManager mService = IConnectivityManager.Stub.asInterface( 56 ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); 57 58 @Override getMetricsCategory()59 public int getMetricsCategory() { 60 return SettingsEnums.DIALOG_VPN_APP_CONFIG; 61 } 62 63 public interface Listener { onForget()64 void onForget(); onCancel()65 void onCancel(); 66 } 67 show(Fragment parent, PackageInfo packageInfo, String label, boolean managing, boolean connected)68 public static void show(Fragment parent, PackageInfo packageInfo, String label, 69 boolean managing, boolean connected) { 70 if (!managing && !connected) { 71 // We can't display anything useful for this case. 72 return; 73 } 74 show(parent, null, packageInfo, label, managing, connected); 75 } 76 show(Fragment parent, Listener listener, PackageInfo packageInfo, String label, boolean managing, boolean connected)77 public static void show(Fragment parent, Listener listener, PackageInfo packageInfo, 78 String label, boolean managing, boolean connected) { 79 if (!parent.isAdded()) { 80 return; 81 } 82 83 Bundle args = new Bundle(); 84 args.putParcelable(ARG_PACKAGE, packageInfo); 85 args.putString(ARG_LABEL, label); 86 args.putBoolean(ARG_MANAGING, managing); 87 args.putBoolean(ARG_CONNECTED, connected); 88 89 final AppDialogFragment frag = new AppDialogFragment(); 90 frag.mListener = listener; 91 frag.setArguments(args); 92 frag.setTargetFragment(parent, 0); 93 frag.show(parent.getFragmentManager(), TAG_APP_DIALOG); 94 } 95 96 @Override onCreate(Bundle savedInstanceState)97 public void onCreate(Bundle savedInstanceState) { 98 super.onCreate(savedInstanceState); 99 mUserManager = UserManager.get(getContext()); 100 } 101 102 @Override onCreateDialog(Bundle savedInstanceState)103 public Dialog onCreateDialog(Bundle savedInstanceState) { 104 Bundle args = getArguments(); 105 final String label = args.getString(ARG_LABEL); 106 boolean managing = args.getBoolean(ARG_MANAGING); 107 boolean connected = args.getBoolean(ARG_CONNECTED); 108 mPackageInfo = args.getParcelable(ARG_PACKAGE); 109 110 if (managing) { 111 return new AppDialog(getActivity(), this, mPackageInfo, label); 112 } else { 113 // Build an AlertDialog with an option to disconnect. 114 AlertDialog.Builder dlog = new AlertDialog.Builder(getActivity()) 115 .setTitle(label) 116 .setMessage(getActivity().getString(R.string.vpn_disconnect_confirm)) 117 .setNegativeButton(getActivity().getString(R.string.vpn_cancel), null); 118 119 if (connected && !isUiRestricted()) { 120 dlog.setPositiveButton(getActivity().getString(R.string.vpn_disconnect), 121 new DialogInterface.OnClickListener() { 122 @Override 123 public void onClick(DialogInterface dialog, int which) { 124 onDisconnect(dialog); 125 } 126 }); 127 } 128 return dlog.create(); 129 } 130 } 131 132 @Override onCancel(DialogInterface dialog)133 public void onCancel(DialogInterface dialog) { 134 dismiss(); 135 if (mListener != null) { 136 mListener.onCancel(); 137 } 138 super.onCancel(dialog); 139 } 140 141 @Override onForget(final DialogInterface dialog)142 public void onForget(final DialogInterface dialog) { 143 if (isUiRestricted()) { 144 return; 145 } 146 final int userId = getUserId(); 147 try { 148 mService.setVpnPackageAuthorization(mPackageInfo.packageName, userId, false); 149 onDisconnect(dialog); 150 } catch (RemoteException e) { 151 Log.e(TAG, "Failed to forget authorization of " + mPackageInfo.packageName + 152 " for user " + userId, e); 153 } 154 155 if (mListener != null) { 156 mListener.onForget(); 157 } 158 } 159 onDisconnect(final DialogInterface dialog)160 private void onDisconnect(final DialogInterface dialog) { 161 if (isUiRestricted()) { 162 return; 163 } 164 final int userId = getUserId(); 165 try { 166 if (mPackageInfo.packageName.equals(VpnUtils.getConnectedPackage(mService, userId))) { 167 mService.setAlwaysOnVpnPackage(userId, null, /* lockdownEnabled */ false, 168 /* lockdownWhitelist */ null); 169 mService.prepareVpn(mPackageInfo.packageName, VpnConfig.LEGACY_VPN, userId); 170 } 171 } catch (RemoteException e) { 172 Log.e(TAG, "Failed to disconnect package " + mPackageInfo.packageName + 173 " for user " + userId, e); 174 } 175 } 176 isUiRestricted()177 private boolean isUiRestricted() { 178 final UserHandle userHandle = UserHandle.of(getUserId()); 179 return mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, userHandle); 180 } 181 getUserId()182 private int getUserId() { 183 return UserHandle.getUserId(mPackageInfo.applicationInfo.uid); 184 } 185 } 186