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