1 /* 2 * Copyright (C) 2011 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.vpndialogs; 18 19 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; 20 21 import android.content.Context; 22 import android.content.DialogInterface; 23 import android.content.pm.PackageManager; 24 import android.graphics.drawable.Drawable; 25 import android.net.IConnectivityManager; 26 import android.net.VpnManager; 27 import android.os.Bundle; 28 import android.os.RemoteException; 29 import android.os.ServiceManager; 30 import android.os.UserHandle; 31 import android.os.UserManager; 32 import android.text.Html; 33 import android.text.Html.ImageGetter; 34 import android.util.Log; 35 import android.util.TypedValue; 36 import android.view.View; 37 import android.widget.Button; 38 import android.widget.TextView; 39 40 import com.android.internal.app.AlertActivity; 41 import com.android.internal.net.VpnConfig; 42 43 public class ConfirmDialog extends AlertActivity 44 implements DialogInterface.OnClickListener, ImageGetter { 45 private static final String TAG = "VpnConfirm"; 46 47 @VpnManager.VpnType private final int mVpnType; 48 49 private String mPackage; 50 51 private IConnectivityManager mService; 52 ConfirmDialog()53 public ConfirmDialog() { 54 this(VpnManager.TYPE_VPN_SERVICE); 55 } 56 ConfirmDialog(@pnManager.VpnType int vpnType)57 public ConfirmDialog(@VpnManager.VpnType int vpnType) { 58 mVpnType = vpnType; 59 } 60 61 @Override onCreate(Bundle savedInstanceState)62 protected void onCreate(Bundle savedInstanceState) { 63 super.onCreate(savedInstanceState); 64 mPackage = getCallingPackage(); 65 mService = IConnectivityManager.Stub.asInterface( 66 ServiceManager.getService(Context.CONNECTIVITY_SERVICE)); 67 68 if (prepareVpn()) { 69 setResult(RESULT_OK); 70 finish(); 71 return; 72 } 73 if (UserManager.get(this).hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN)) { 74 finish(); 75 return; 76 } 77 final String alwaysOnVpnPackage = getAlwaysOnVpnPackage(); 78 // Can't prepare new vpn app when another vpn is always-on 79 if (alwaysOnVpnPackage != null && !alwaysOnVpnPackage.equals(mPackage)) { 80 finish(); 81 return; 82 } 83 View view = View.inflate(this, R.layout.confirm, null); 84 ((TextView) view.findViewById(R.id.warning)).setText( 85 Html.fromHtml(getString(R.string.warning, getVpnLabel()), 86 this, null /* tagHandler */)); 87 mAlertParams.mTitle = getText(R.string.prompt); 88 mAlertParams.mPositiveButtonText = getText(android.R.string.ok); 89 mAlertParams.mPositiveButtonListener = this; 90 mAlertParams.mNegativeButtonText = getText(android.R.string.cancel); 91 mAlertParams.mView = view; 92 setupAlert(); 93 94 getWindow().setCloseOnTouchOutside(false); 95 getWindow().addPrivateFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); 96 Button button = mAlert.getButton(DialogInterface.BUTTON_POSITIVE); 97 button.setFilterTouchesWhenObscured(true); 98 } 99 getAlwaysOnVpnPackage()100 private String getAlwaysOnVpnPackage() { 101 try { 102 return mService.getAlwaysOnVpnPackage(UserHandle.myUserId()); 103 } catch (RemoteException e) { 104 Log.e(TAG, "fail to call getAlwaysOnVpnPackage", e); 105 // Fallback to null to show the dialog 106 return null; 107 } 108 } 109 prepareVpn()110 private boolean prepareVpn() { 111 try { 112 return mService.prepareVpn(mPackage, null, UserHandle.myUserId()); 113 } catch (RemoteException e) { 114 throw new IllegalStateException(e); 115 } 116 } 117 getVpnLabel()118 private CharSequence getVpnLabel() { 119 try { 120 return VpnConfig.getVpnLabel(this, mPackage); 121 } catch (PackageManager.NameNotFoundException e) { 122 throw new IllegalStateException(e); 123 } 124 } 125 126 @Override getDrawable(String source)127 public Drawable getDrawable(String source) { 128 // Should only reach this when fetching the VPN icon for the warning string. 129 final Drawable icon = getDrawable(R.drawable.ic_vpn_dialog); 130 icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight()); 131 132 final TypedValue tv = new TypedValue(); 133 if (getTheme().resolveAttribute(android.R.attr.textColorPrimary, tv, true)) { 134 icon.setTint(getColor(tv.resourceId)); 135 } else { 136 Log.w(TAG, "Unable to resolve theme color"); 137 } 138 139 return icon; 140 } 141 142 @Override onBackPressed()143 public void onBackPressed() { 144 } 145 146 @Override onClick(DialogInterface dialog, int which)147 public void onClick(DialogInterface dialog, int which) { 148 try { 149 if (mService.prepareVpn(null, mPackage, UserHandle.myUserId())) { 150 // Authorize this app to initiate VPN connections in the future without user 151 // intervention. 152 mService.setVpnPackageAuthorization(mPackage, UserHandle.myUserId(), mVpnType); 153 setResult(RESULT_OK); 154 } 155 } catch (Exception e) { 156 Log.e(TAG, "onClick", e); 157 } 158 } 159 } 160