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