11617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan/* 2d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan * Copyright (C) 2009 The Android Open Source Project 31617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan * 41617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan * Licensed under the Apache License, Version 2.0 (the "License"); 51617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan * you may not use this file except in compliance with the License. 61617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan * You may obtain a copy of the License at 71617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan * 81617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan * http://www.apache.org/licenses/LICENSE-2.0 91617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan * 101617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan * Unless required by applicable law or agreed to in writing, software 111617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan * distributed under the License is distributed on an "AS IS" BASIS, 121617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan * See the License for the specific language governing permissions and 141617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan * limitations under the License. 151617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan */ 161617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 171617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyanpackage com.android.settings.vpn; 181617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 191617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyanimport com.android.settings.R; 201617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 21d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyanimport android.app.Dialog; 221617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyanimport android.content.ComponentName; 231617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyanimport android.content.Context; 241617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyanimport android.content.ServiceConnection; 251617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyanimport android.net.vpn.IVpnService; 261617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyanimport android.net.vpn.VpnManager; 271617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyanimport android.net.vpn.VpnProfile; 281617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyanimport android.net.vpn.VpnState; 29ba127f57ae143a0c7fad5a46b327c04eb2254737Hung-ying Tyanimport android.os.ConditionVariable; 301617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyanimport android.os.IBinder; 311617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyanimport android.os.RemoteException; 32e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyanimport android.text.TextUtils; 331617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyanimport android.util.Log; 341617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyanimport android.view.View; 35d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyanimport android.widget.CheckBox; 361617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyanimport android.widget.TextView; 371617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 38e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyanimport java.io.IOException; 39e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan 401617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan/** 41d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan * A {@link VpnProfileActor} that provides an authentication view for users to 42d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan * input username and password before connecting to the VPN server. 431617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan */ 44d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyanpublic class AuthenticationActor implements VpnProfileActor { 451617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan private static final String TAG = AuthenticationActor.class.getName(); 461617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 471617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan private Context mContext; 481617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan private VpnProfile mProfile; 491617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan private VpnManager mVpnManager; 501617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 511617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan public AuthenticationActor(Context context, VpnProfile p) { 521617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan mContext = context; 531617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan mProfile = p; 541617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan mVpnManager = new VpnManager(context); 551617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 561617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 571617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan //@Override 581617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan public VpnProfile getProfile() { 591617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan return mProfile; 601617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 611617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 621617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan //@Override 63d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan public boolean isConnectDialogNeeded() { 64d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan return true; 651617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 661617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 671617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan //@Override 68d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan public String validateInputs(Dialog d) { 69d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan TextView usernameView = (TextView) d.findViewById(R.id.username_value); 70d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan TextView passwordView = (TextView) d.findViewById(R.id.password_value); 711617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan Context c = mContext; 72e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan if (TextUtils.isEmpty(usernameView.getText().toString())) { 7333ababd1bdb651d32952536e6d5e72750d1f4cc9Hung-ying Tyan return c.getString(R.string.vpn_a_username); 74e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan } else if (TextUtils.isEmpty(passwordView.getText().toString())) { 7533ababd1bdb651d32952536e6d5e72750d1f4cc9Hung-ying Tyan return c.getString(R.string.vpn_a_password); 76d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan } else { 77d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan return null; 78d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan } 791617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 801617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 811617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan //@Override 82d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan public void connect(Dialog d) { 83d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan TextView usernameView = (TextView) d.findViewById(R.id.username_value); 84d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan TextView passwordView = (TextView) d.findViewById(R.id.password_value); 85d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan CheckBox saveUsername = (CheckBox) d.findViewById(R.id.save_username); 86d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan 87e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan try { 88e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan setSavedUsername(saveUsername.isChecked() 89e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan ? usernameView.getText().toString() 90e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan : ""); 91e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan } catch (IOException e) { 92e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan Log.e(TAG, "setSavedUsername()", e); 931617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 94e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan 95d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan connect(usernameView.getText().toString(), 96d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan passwordView.getText().toString()); 97d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan passwordView.setText(""); 981617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 991617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 1001617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan //@Override 101d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan public View createConnectView() { 1021ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan View v = View.inflate(mContext, R.layout.vpn_connect_dialog_view, null); 1031ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan TextView usernameView = (TextView) v.findViewById(R.id.username_value); 1041ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan TextView passwordView = (TextView) v.findViewById(R.id.password_value); 1051ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan CheckBox saveUsername = (CheckBox) v.findViewById(R.id.save_username); 1061617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 107d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan String username = mProfile.getSavedUsername(); 1081ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan if (!TextUtils.isEmpty(username)) { 1091ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan usernameView.setText(username); 1101ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan saveUsername.setChecked(true); 1111ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan passwordView.requestFocus(); 1121ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan } 1131ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan return v; 114e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan } 115e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan 116e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan protected Context getContext() { 117e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan return mContext; 1181617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 1191617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 120d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan private void connect(final String username, final String password) { 1211617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan mVpnManager.startVpnService(); 1221617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan ServiceConnection c = new ServiceConnection() { 1231617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan public void onServiceConnected(ComponentName className, 1241617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan IBinder service) { 1251617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan try { 1261ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan boolean success = IVpnService.Stub.asInterface(service) 127d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan .connect(mProfile, username, password); 1281617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan if (!success) { 1291617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan Log.d(TAG, "~~~~~~ connect() failed!"); 1301617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } else { 1311617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan Log.d(TAG, "~~~~~~ connect() succeeded!"); 1321617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 1331ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan } catch (Throwable e) { 1341ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan Log.e(TAG, "connect()", e); 1351ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan broadcastConnectivity(VpnState.IDLE, 1361ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan VpnManager.VPN_ERROR_CONNECTION_FAILED); 1371ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan } finally { 1381ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan mContext.unbindService(this); 1391617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 1401617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 1411617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 1421617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan public void onServiceDisconnected(ComponentName className) { 1431617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan checkStatus(); 1441617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 1451617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan }; 1461ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan if (!bindService(c)) { 1471ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan broadcastConnectivity(VpnState.IDLE, 1481ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan VpnManager.VPN_ERROR_CONNECTION_FAILED); 1491ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan } 1501617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 1511617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 1521617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan //@Override 1531617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan public void disconnect() { 1541617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan ServiceConnection c = new ServiceConnection() { 1551617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan public void onServiceConnected(ComponentName className, 1561617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan IBinder service) { 1571617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan try { 1581617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan IVpnService.Stub.asInterface(service).disconnect(); 1591617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } catch (RemoteException e) { 1601617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan Log.e(TAG, "disconnect()", e); 1611617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan checkStatus(); 1621617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } finally { 1631617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan mContext.unbindService(this); 1641617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 1651617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 1661617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 1671617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan public void onServiceDisconnected(ComponentName className) { 1681617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan checkStatus(); 1691617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 1701617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan }; 1711ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan if (!bindService(c)) { 1721ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan checkStatus(); 1731ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan } 1741617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 1751617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 1761617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan //@Override 1771617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan public void checkStatus() { 178ba127f57ae143a0c7fad5a46b327c04eb2254737Hung-ying Tyan final ConditionVariable cv = new ConditionVariable(); 179ba127f57ae143a0c7fad5a46b327c04eb2254737Hung-ying Tyan cv.close(); 1801617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan ServiceConnection c = new ServiceConnection() { 1811617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan public synchronized void onServiceConnected(ComponentName className, 1821617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan IBinder service) { 183ba127f57ae143a0c7fad5a46b327c04eb2254737Hung-ying Tyan cv.open(); 1841617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan try { 1851617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan IVpnService.Stub.asInterface(service).checkStatus(mProfile); 1861ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan } catch (RemoteException e) { 1871617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan Log.e(TAG, "checkStatus()", e); 1881ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan broadcastConnectivity(VpnState.IDLE); 1891617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } finally { 190ba127f57ae143a0c7fad5a46b327c04eb2254737Hung-ying Tyan mContext.unbindService(this); 1911617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 1921617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 1931617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 1941617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan public void onServiceDisconnected(ComponentName className) { 195ba127f57ae143a0c7fad5a46b327c04eb2254737Hung-ying Tyan cv.open(); 196ba127f57ae143a0c7fad5a46b327c04eb2254737Hung-ying Tyan broadcastConnectivity(VpnState.IDLE); 197ba127f57ae143a0c7fad5a46b327c04eb2254737Hung-ying Tyan mContext.unbindService(this); 1981617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 1991617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan }; 2001617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan if (bindService(c)) { 2011617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan // wait for a second, let status propagate 202ba127f57ae143a0c7fad5a46b327c04eb2254737Hung-ying Tyan if (!cv.block(1000)) broadcastConnectivity(VpnState.IDLE); 2031617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 2041617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 2051617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 2061617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan private boolean bindService(ServiceConnection c) { 2071617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan return mVpnManager.bindVpnService(c); 2081617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 2091617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 210d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan private void broadcastConnectivity(VpnState s) { 211d22da2096bd738346be5e24eb964ae34d60fcd5eHung-ying Tyan mVpnManager.broadcastConnectivity(mProfile.getName(), s); 2121617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan } 2131617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan 2141ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan private void broadcastConnectivity(VpnState s, int errorCode) { 2151ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan mVpnManager.broadcastConnectivity(mProfile.getName(), s, errorCode); 2161ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan } 2171ddccd07f744344b5248dd5418ee526f26d520dcHung-ying Tyan 218e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan private void setSavedUsername(String name) throws IOException { 219e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan if (!name.equals(mProfile.getSavedUsername())) { 220e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan mProfile.setSavedUsername(name); 221e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan VpnSettings.saveProfileToStorage(mProfile); 222e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan } 223e7565f3c48e6c90e65d9c15e33d20673a187c156Hung-ying Tyan } 2241617706d2529b2182d1a7fe2348495fb8f40bb81Hung-ying Tyan} 225