+ mTerminate = true;
+ setNextProfile(null);
+ try
+ {
+ mConnectionHandler.join();
+ }
+ catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ mDataSource.close();
+ }
+
+ /**
+ * Set the profile that is to be initiated next. Notify the handler thread.
+ *
+ * @param profile the profile to initiate
+ */
+ private void setNextProfile(VpnProfile profile)
+ {
+ synchronized (this)
+ {
+ this.mNextProfile = profile;
+ mProfileUpdated = true;
+ notifyAll();
+ }
+ }
+
+ @Override
+ public void run()
+ {
+ while (true)
+ {
+ synchronized (this)
+ {
+ try
+ {
+ while (!mProfileUpdated)
+ {
+ wait();
+ }
+
+ mProfileUpdated = false;
+ stopCurrentConnection();
+ if (mNextProfile == null)
+ {
+ if (mTerminate)
+ {
+ break;
+ }
+ }
+ else
+ {
+ mCurrentProfile = mNextProfile;
+ mNextProfile = null;
+
+ initializeCharon();
+ Log.i(TAG, "charon started");
+ }
+ }
+ catch (InterruptedException ex)
+ {
+ stopCurrentConnection();
+ }
+ }
+ }
+ }
+
+ /**
+ * Stop any existing connection by deinitializing charon.
+ */
+ private void stopCurrentConnection()
+ {
+ synchronized (this)
+ {
+ if (mCurrentProfile != null)
+ {
+ deinitializeCharon();
+ Log.i(TAG, "charon stopped");
+ mCurrentProfile = null;
+ }
+ }