am ba127f57
: Improve VpnSettings start-up time.
Merge commit 'ba127f57ae143a0c7fad5a46b327c04eb2254737' * commit 'ba127f57ae143a0c7fad5a46b327c04eb2254737': Improve VpnSettings start-up time.
This commit is contained in:
@@ -127,6 +127,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name=".vpn.VpnSettings"
|
<activity android:name=".vpn.VpnSettings"
|
||||||
|
android:configChanges="orientation|keyboardHidden"
|
||||||
android:launchMode="singleTask">
|
android:launchMode="singleTask">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
@@ -136,8 +137,12 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name=".vpn.VpnTypeSelection"></activity>
|
<activity android:name=".vpn.VpnTypeSelection"
|
||||||
<activity android:name=".vpn.VpnEditor"></activity>
|
android:configChanges="orientation|keyboardHidden">
|
||||||
|
</activity>
|
||||||
|
<activity android:name=".vpn.VpnEditor"
|
||||||
|
android:configChanges="orientation|keyboardHidden">
|
||||||
|
</activity>
|
||||||
|
|
||||||
<activity android:name="DateTimeSettings" android:label="@string/date_and_time"
|
<activity android:name="DateTimeSettings" android:label="@string/date_and_time"
|
||||||
>
|
>
|
||||||
@@ -270,6 +275,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name="SecuritySettings" android:label="@string/security_settings_title"
|
<activity android:name="SecuritySettings" android:label="@string/security_settings_title"
|
||||||
|
android:configChanges="orientation|keyboardHidden"
|
||||||
android:clearTaskOnLaunch="true"
|
android:clearTaskOnLaunch="true"
|
||||||
>
|
>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
@@ -26,6 +26,7 @@ import android.net.vpn.IVpnService;
|
|||||||
import android.net.vpn.VpnManager;
|
import android.net.vpn.VpnManager;
|
||||||
import android.net.vpn.VpnProfile;
|
import android.net.vpn.VpnProfile;
|
||||||
import android.net.vpn.VpnState;
|
import android.net.vpn.VpnState;
|
||||||
|
import android.os.ConditionVariable;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@@ -42,7 +43,6 @@ import java.io.IOException;
|
|||||||
*/
|
*/
|
||||||
public class AuthenticationActor implements VpnProfileActor {
|
public class AuthenticationActor implements VpnProfileActor {
|
||||||
private static final String TAG = AuthenticationActor.class.getName();
|
private static final String TAG = AuthenticationActor.class.getName();
|
||||||
private static final int ONE_SECOND = 1000; // ms
|
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private VpnProfile mProfile;
|
private VpnProfile mProfile;
|
||||||
@@ -175,27 +175,31 @@ public class AuthenticationActor implements VpnProfileActor {
|
|||||||
|
|
||||||
//@Override
|
//@Override
|
||||||
public void checkStatus() {
|
public void checkStatus() {
|
||||||
|
final ConditionVariable cv = new ConditionVariable();
|
||||||
|
cv.close();
|
||||||
ServiceConnection c = new ServiceConnection() {
|
ServiceConnection c = new ServiceConnection() {
|
||||||
public synchronized void onServiceConnected(ComponentName className,
|
public synchronized void onServiceConnected(ComponentName className,
|
||||||
IBinder service) {
|
IBinder service) {
|
||||||
|
cv.open();
|
||||||
try {
|
try {
|
||||||
IVpnService.Stub.asInterface(service).checkStatus(mProfile);
|
IVpnService.Stub.asInterface(service).checkStatus(mProfile);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "checkStatus()", e);
|
Log.e(TAG, "checkStatus()", e);
|
||||||
broadcastConnectivity(VpnState.IDLE);
|
broadcastConnectivity(VpnState.IDLE);
|
||||||
} finally {
|
} finally {
|
||||||
notify();
|
mContext.unbindService(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onServiceDisconnected(ComponentName className) {
|
public void onServiceDisconnected(ComponentName className) {
|
||||||
// do nothing
|
cv.open();
|
||||||
|
broadcastConnectivity(VpnState.IDLE);
|
||||||
|
mContext.unbindService(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (bindService(c)) {
|
if (bindService(c)) {
|
||||||
// wait for a second, let status propagate
|
// wait for a second, let status propagate
|
||||||
wait(c, ONE_SECOND);
|
if (!cv.block(1000)) broadcastConnectivity(VpnState.IDLE);
|
||||||
mContext.unbindService(c);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,14 +215,6 @@ public class AuthenticationActor implements VpnProfileActor {
|
|||||||
mVpnManager.broadcastConnectivity(mProfile.getName(), s, errorCode);
|
mVpnManager.broadcastConnectivity(mProfile.getName(), s, errorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void wait(Object o, int ms) {
|
|
||||||
synchronized (o) {
|
|
||||||
try {
|
|
||||||
o.wait(ms);
|
|
||||||
} catch (Exception e) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSavedUsername(String name) throws IOException {
|
private void setSavedUsername(String name) throws IOException {
|
||||||
if (!name.equals(mProfile.getSavedUsername())) {
|
if (!name.equals(mProfile.getSavedUsername())) {
|
||||||
mProfile.setSavedUsername(name);
|
mProfile.setSavedUsername(name);
|
||||||
|
@@ -21,10 +21,13 @@ import com.android.settings.SecuritySettings;
|
|||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
|
import android.net.vpn.IVpnService;
|
||||||
import android.net.vpn.L2tpIpsecPskProfile;
|
import android.net.vpn.L2tpIpsecPskProfile;
|
||||||
import android.net.vpn.L2tpProfile;
|
import android.net.vpn.L2tpProfile;
|
||||||
import android.net.vpn.VpnManager;
|
import android.net.vpn.VpnManager;
|
||||||
@@ -33,8 +36,10 @@ import android.net.vpn.VpnState;
|
|||||||
import android.net.vpn.VpnType;
|
import android.net.vpn.VpnType;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.ConditionVariable;
|
import android.os.ConditionVariable;
|
||||||
|
import android.os.IBinder;
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceActivity;
|
import android.preference.PreferenceActivity;
|
||||||
import android.preference.PreferenceCategory;
|
import android.preference.PreferenceCategory;
|
||||||
@@ -86,8 +91,6 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
private static final String PROFILES_ROOT = VpnManager.PROFILES_PATH + "/";
|
private static final String PROFILES_ROOT = VpnManager.PROFILES_PATH + "/";
|
||||||
private static final String PROFILE_OBJ_FILE = ".pobj";
|
private static final String PROFILE_OBJ_FILE = ".pobj";
|
||||||
|
|
||||||
private static final String STATE_ACTIVE_ACTOR = "active_actor";
|
|
||||||
|
|
||||||
private static final int REQUEST_ADD_OR_EDIT_PROFILE = 1;
|
private static final int REQUEST_ADD_OR_EDIT_PROFILE = 1;
|
||||||
private static final int REQUEST_SELECT_VPN_TYPE = 2;
|
private static final int REQUEST_SELECT_VPN_TYPE = 2;
|
||||||
|
|
||||||
@@ -113,8 +116,6 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
private Map<String, VpnPreference> mVpnPreferenceMap;
|
private Map<String, VpnPreference> mVpnPreferenceMap;
|
||||||
private List<VpnProfile> mVpnProfileList;
|
private List<VpnProfile> mVpnProfileList;
|
||||||
|
|
||||||
private int mIndexOfEditedProfile = -1;
|
|
||||||
|
|
||||||
// profile engaged in a connection
|
// profile engaged in a connection
|
||||||
private VpnProfile mActiveProfile;
|
private VpnProfile mActiveProfile;
|
||||||
|
|
||||||
@@ -159,28 +160,13 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
// listen to vpn connectivity event
|
// listen to vpn connectivity event
|
||||||
mVpnManager.registerConnectivityReceiver(mConnectivityReceiver);
|
mVpnManager.registerConnectivityReceiver(mConnectivityReceiver);
|
||||||
|
|
||||||
String profileName = (savedInstanceState == null)
|
|
||||||
? null
|
|
||||||
: savedInstanceState.getString(STATE_ACTIVE_ACTOR);
|
|
||||||
retrieveVpnListFromStorage();
|
retrieveVpnListFromStorage();
|
||||||
if (!TextUtils.isEmpty(profileName)) {
|
checkVpnConnectionStatusInBackground();
|
||||||
mActiveProfile = mVpnPreferenceMap.get(profileName).mProfile;
|
|
||||||
mConnectingActor = getActor(mActiveProfile);
|
|
||||||
} else {
|
|
||||||
checkVpnConnectionStatusInBackground();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause() {
|
|
||||||
super.onPause();
|
|
||||||
mStatusChecker.onPause();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
mStatusChecker.onResume();
|
|
||||||
|
|
||||||
if ((mUnlockAction != null) && isKeystoreUnlocked()) {
|
if ((mUnlockAction != null) && isKeystoreUnlocked()) {
|
||||||
Runnable action = mUnlockAction;
|
Runnable action = mUnlockAction;
|
||||||
@@ -189,15 +175,6 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected synchronized void onSaveInstanceState(Bundle outState) {
|
|
||||||
if (mConnectingActor == null) return;
|
|
||||||
|
|
||||||
Log.d(TAG, " ~~~~~ save connecting actor");
|
|
||||||
outState.putString(STATE_ACTIVE_ACTOR,
|
|
||||||
mConnectingActor.getProfile().getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
@@ -278,8 +255,6 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
public void onClick(DialogInterface dialog, int w) {
|
public void onClick(DialogInterface dialog, int w) {
|
||||||
VpnProfile p = mConnectingActor.getProfile();
|
VpnProfile p = mConnectingActor.getProfile();
|
||||||
onIdle();
|
onIdle();
|
||||||
mIndexOfEditedProfile =
|
|
||||||
mVpnProfileList.indexOf(p);
|
|
||||||
startVpnEditor(p);
|
startVpnEditor(p);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -325,7 +300,6 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case CONTEXT_MENU_EDIT_ID:
|
case CONTEXT_MENU_EDIT_ID:
|
||||||
mIndexOfEditedProfile = position;
|
|
||||||
startVpnEditor(p);
|
startVpnEditor(p);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -340,9 +314,6 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
@Override
|
@Override
|
||||||
protected void onActivityResult(final int requestCode, final int resultCode,
|
protected void onActivityResult(final int requestCode, final int resultCode,
|
||||||
final Intent data) {
|
final Intent data) {
|
||||||
final int index = mIndexOfEditedProfile;
|
|
||||||
mIndexOfEditedProfile = -1;
|
|
||||||
|
|
||||||
if ((resultCode == RESULT_CANCELED) || (data == null)) {
|
if ((resultCode == RESULT_CANCELED) || (data == null)) {
|
||||||
Log.d(TAG, "no result returned by editor");
|
Log.d(TAG, "no result returned by editor");
|
||||||
return;
|
return;
|
||||||
@@ -358,6 +329,7 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int index = getProfileIndexFromId(p.getId());
|
||||||
if (checkDuplicateName(p, index)) {
|
if (checkDuplicateName(p, index)) {
|
||||||
final VpnProfile profile = p;
|
final VpnProfile profile = p;
|
||||||
Util.showErrorMessage(this, String.format(
|
Util.showErrorMessage(this, String.format(
|
||||||
@@ -374,7 +346,6 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
if (needKeystoreToSave(p)) {
|
if (needKeystoreToSave(p)) {
|
||||||
Runnable action = new Runnable() {
|
Runnable action = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
mIndexOfEditedProfile = index;
|
|
||||||
onActivityResult(requestCode, resultCode, data);
|
onActivityResult(requestCode, resultCode, data);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -382,7 +353,7 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ((index < 0) || (index >= mVpnProfileList.size())) {
|
if (index < 0) {
|
||||||
addProfile(p);
|
addProfile(p);
|
||||||
Util.showShortToastMessage(this, String.format(
|
Util.showShortToastMessage(this, String.format(
|
||||||
getString(R.string.vpn_profile_added), p.getName()));
|
getString(R.string.vpn_profile_added), p.getName()));
|
||||||
@@ -440,6 +411,18 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getProfileIndexFromId(String id) {
|
||||||
|
int index = 0;
|
||||||
|
for (VpnProfile p : mVpnProfileList) {
|
||||||
|
if (p.getId().equals(id)) {
|
||||||
|
return index;
|
||||||
|
} else {
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Replaces the profile at index in mVpnProfileList with p.
|
// Replaces the profile at index in mVpnProfileList with p.
|
||||||
// Returns true if p's name is a duplicate.
|
// Returns true if p's name is a duplicate.
|
||||||
private boolean checkDuplicateName(VpnProfile p, int index) {
|
private boolean checkDuplicateName(VpnProfile p, int index) {
|
||||||
@@ -517,11 +500,16 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
disableProfilePreferencesIfOneActive();
|
disableProfilePreferencesIfOneActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private VpnPreference addPreferenceFor(VpnProfile p) {
|
||||||
|
return addPreferenceFor(p, true);
|
||||||
|
}
|
||||||
|
|
||||||
// Adds a preference in mVpnListContainer
|
// Adds a preference in mVpnListContainer
|
||||||
private void addPreferenceFor(VpnProfile p) {
|
private VpnPreference addPreferenceFor(
|
||||||
|
VpnProfile p, boolean addToContainer) {
|
||||||
VpnPreference pref = new VpnPreference(this, p);
|
VpnPreference pref = new VpnPreference(this, p);
|
||||||
mVpnPreferenceMap.put(p.getName(), pref);
|
mVpnPreferenceMap.put(p.getName(), pref);
|
||||||
mVpnListContainer.addPreference(pref);
|
if (addToContainer) mVpnListContainer.addPreference(pref);
|
||||||
|
|
||||||
pref.setOnPreferenceClickListener(
|
pref.setOnPreferenceClickListener(
|
||||||
new Preference.OnPreferenceClickListener() {
|
new Preference.OnPreferenceClickListener() {
|
||||||
@@ -530,6 +518,7 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return pref;
|
||||||
}
|
}
|
||||||
|
|
||||||
// index: index to mVpnProfileList
|
// index: index to mVpnProfileList
|
||||||
@@ -790,12 +779,18 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
for (VpnProfile p : mVpnProfileList) addPreferenceFor(p);
|
for (VpnProfile p : mVpnProfileList) {
|
||||||
|
Preference pref = addPreferenceFor(p, false);
|
||||||
|
}
|
||||||
disableProfilePreferencesIfOneActive();
|
disableProfilePreferencesIfOneActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkVpnConnectionStatusInBackground() {
|
private void checkVpnConnectionStatusInBackground() {
|
||||||
mStatusChecker.check(mVpnProfileList);
|
new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
mStatusChecker.check(mVpnProfileList);
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
// A sanity check. Returns true if the profile directory name and profile ID
|
// A sanity check. Returns true if the profile directory name and profile ID
|
||||||
@@ -931,49 +926,58 @@ public class VpnSettings extends PreferenceActivity implements
|
|||||||
|
|
||||||
// managing status check in a background thread
|
// managing status check in a background thread
|
||||||
private class StatusChecker {
|
private class StatusChecker {
|
||||||
private Set<VpnProfile> mQueue = new HashSet<VpnProfile>();
|
private List<VpnProfile> mList;
|
||||||
private boolean mPaused = true;
|
|
||||||
private ConditionVariable mThreadCv = new ConditionVariable();
|
|
||||||
|
|
||||||
void onPause() {
|
synchronized void check(final List<VpnProfile> list) {
|
||||||
mPaused = true;
|
final ConditionVariable cv = new ConditionVariable();
|
||||||
mThreadCv.block(); // until the checking thread is over
|
cv.close();
|
||||||
}
|
mVpnManager.startVpnService();
|
||||||
|
ServiceConnection c = new ServiceConnection() {
|
||||||
|
public synchronized void onServiceConnected(
|
||||||
|
ComponentName className, IBinder binder) {
|
||||||
|
cv.open();
|
||||||
|
|
||||||
synchronized void onResume() {
|
IVpnService service = IVpnService.Stub.asInterface(binder);
|
||||||
start();
|
for (VpnProfile p : list) {
|
||||||
}
|
try {
|
||||||
|
service.checkStatus(p);
|
||||||
synchronized void check(List<VpnProfile> list) {
|
} catch (Throwable e) {
|
||||||
boolean started = !mQueue.isEmpty();
|
Log.e(TAG, " --- checkStatus(): " + p.getName(), e);
|
||||||
for (VpnProfile p : list) {
|
changeState(p, VpnState.IDLE);
|
||||||
if (!mQueue.contains(p)) mQueue.add(p);
|
}
|
||||||
}
|
|
||||||
if (!started) start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized VpnProfile next() {
|
|
||||||
if (mPaused || mQueue.isEmpty()) return null;
|
|
||||||
Iterator<VpnProfile> i = mQueue.iterator();
|
|
||||||
VpnProfile p = i.next();
|
|
||||||
i.remove();
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void start() {
|
|
||||||
if (!mPaused) return;
|
|
||||||
mPaused = false;
|
|
||||||
mThreadCv.close();
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
while (true) {
|
|
||||||
VpnProfile p = next();
|
|
||||||
if (p == null) break;
|
|
||||||
getActor(p).checkStatus();
|
|
||||||
}
|
}
|
||||||
mThreadCv.open();
|
VpnSettings.this.unbindService(this);
|
||||||
|
showPreferences();
|
||||||
}
|
}
|
||||||
}).start();
|
|
||||||
|
public void onServiceDisconnected(ComponentName className) {
|
||||||
|
cv.open();
|
||||||
|
|
||||||
|
setDefaultState(list);
|
||||||
|
VpnSettings.this.unbindService(this);
|
||||||
|
showPreferences();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (mVpnManager.bindVpnService(c)) {
|
||||||
|
if (!cv.block(1000)) {
|
||||||
|
Log.d(TAG, "checkStatus() bindService failed");
|
||||||
|
setDefaultState(list);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setDefaultState(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showPreferences() {
|
||||||
|
for (VpnProfile p : mVpnProfileList) {
|
||||||
|
VpnPreference pref = mVpnPreferenceMap.get(p.getName());
|
||||||
|
mVpnListContainer.addPreference(pref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDefaultState(List<VpnProfile> list) {
|
||||||
|
for (VpnProfile p : list) changeState(p, VpnState.IDLE);
|
||||||
|
showPreferences();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user