@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  private void jbNotificationExtras(
      boolean lowpriority, android.app.Notification.Builder nbuilder) {
    try {
      if (lowpriority) {
        Method setpriority = nbuilder.getClass().getMethod("setPriority", int.class);
        // PRIORITY_MIN == -2
        setpriority.invoke(nbuilder, -2);

        Method setUsesChronometer =
            nbuilder.getClass().getMethod("setUsesChronometer", boolean.class);
        setUsesChronometer.invoke(nbuilder, true);
      }

      Intent disconnectVPN = new Intent(this, DisconnectVPN.class);
      disconnectVPN.setAction(DISCONNECT_VPN);
      PendingIntent disconnectPendingIntent = PendingIntent.getActivity(this, 0, disconnectVPN, 0);

      nbuilder.addAction(
          android.R.drawable.ic_menu_close_clear_cancel,
          getString(R.string.cancel_connection),
          disconnectPendingIntent);

      Intent pauseVPN = new Intent(this, OpenVPNService.class);
      if (mDeviceStateReceiver == null || !mDeviceStateReceiver.isUserPaused()) {
        pauseVPN.setAction(PAUSE_VPN);
        PendingIntent pauseVPNPending = PendingIntent.getService(this, 0, pauseVPN, 0);
        nbuilder.addAction(
            android.R.drawable.ic_media_pause, getString(R.string.pauseVPN), pauseVPNPending);

      } else {
        pauseVPN.setAction(RESUME_VPN);
        PendingIntent resumeVPNPending = PendingIntent.getService(this, 0, pauseVPN, 0);
        nbuilder.addAction(
            android.R.drawable.ic_media_play, getString(R.string.resumevpn), resumeVPNPending);
      }

      // ignore exception
    } catch (NoSuchMethodException
        | IllegalArgumentException
        | InvocationTargetException
        | IllegalAccessException e) {
      VpnStatus.logException(e);
    }
  }
  @Override
  public int onStartCommand(Intent intent, int flags, int startId) {

    if (intent != null && intent.getBooleanExtra(ALWAYS_SHOW_NOTIFICATION, false))
      mNotificationAlwaysVisible = true;

    VpnStatus.addStateListener(this);
    VpnStatus.addByteCountListener(this);

    if (intent != null && PAUSE_VPN.equals(intent.getAction())) {
      if (mDeviceStateReceiver != null) mDeviceStateReceiver.userPause(true);
      return START_NOT_STICKY;
    }

    if (intent != null && RESUME_VPN.equals(intent.getAction())) {
      if (mDeviceStateReceiver != null) mDeviceStateReceiver.userPause(false);
      return START_NOT_STICKY;
    }

    if (intent != null && START_SERVICE.equals(intent.getAction())) return START_NOT_STICKY;
    if (intent != null && START_SERVICE_STICKY.equals(intent.getAction())) {
      return START_REDELIVER_INTENT;
    }

    /* The intent is null when the service has been restarted */
    if (intent == null) {
      mProfile = ProfileManager.getLastConnectedProfile(this, false);
      VpnStatus.logInfo(R.string.service_restarted);

      /* Got no profile, just stop */
      if (mProfile == null) {
        Log.d("OpenVPN", "Got no last connected profile on null intent. Stopping");
        stopSelf(startId);
        return START_NOT_STICKY;
      }
      /* Do the asynchronous keychain certificate stuff */
      mProfile.checkForRestart(this);

      /* Recreate the intent */
      intent = mProfile.getStartServiceIntent(this);

    } else {
      String profileUUID = intent.getStringExtra(getPackageName() + ".profileUUID");
      mProfile = ProfileManager.get(this, profileUUID);
    }

    // Extract information from the intent.
    String prefix = getPackageName();
    String[] argv = intent.getStringArrayExtra(prefix + ".ARGV");
    String nativeLibraryDirectory = intent.getStringExtra(prefix + ".nativelib");

    String startTitle = getString(R.string.start_vpn_title, mProfile.mName);
    String startTicker = getString(R.string.start_vpn_ticker, mProfile.mName);
    showNotification(startTitle, startTicker, false, 0, LEVEL_CONNECTING_NO_SERVER_REPLY_YET);

    // Set a flag that we are starting a new VPN
    mStarting = true;
    // Stop the previous session by interrupting the thread.
    if (mManagement != null && mManagement.stopVPN())
      // an old was asked to exit, wait 1s
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        // ignore
      }

    synchronized (mProcessLock) {
      if (mProcessThread != null) {
        mProcessThread.interrupt();
        try {
          Thread.sleep(1000);
        } catch (InterruptedException e) {
          // ignore
        }
      }
    }
    // An old running VPN should now be exited
    mStarting = false;

    // Start a new session by creating a new thread.
    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

    mOvpn3 = prefs.getBoolean("ovpn3", false);
    if (!"ovpn3".equals(BuildConfig.FLAVOR)) mOvpn3 = false;

    // Open the Management Interface
    if (!mOvpn3) {

      // start a Thread that handles incoming messages of the managment socket
      OpenVpnManagementThread ovpnManagementThread = new OpenVpnManagementThread(mProfile, this);
      if (ovpnManagementThread.openManagementInterface(this)) {

        Thread mSocketManagerThread = new Thread(ovpnManagementThread, "OpenVPNManagementThread");
        mSocketManagerThread.start();
        mManagement = ovpnManagementThread;
        VpnStatus.logInfo("started Socket Thread");
      } else {
        return START_NOT_STICKY;
      }
    }

    Runnable processThread;
    if (mOvpn3) {

      OpenVPNManagement mOpenVPN3 = instantiateOpenVPN3Core();
      processThread = (Runnable) mOpenVPN3;
      mManagement = mOpenVPN3;

    } else {
      HashMap<String, String> env = new HashMap<>();
      processThread = new OpenVPNThread(this, argv, env, nativeLibraryDirectory);
    }

    synchronized (mProcessLock) {
      mProcessThread = new Thread(processThread, "OpenVPNProcessThread");
      mProcessThread.start();
    }
    if (mDeviceStateReceiver != null) unregisterDeviceStateReceiver();

    registerDeviceStateReceiver(mManagement);

    ProfileManager.setConnectedVpnProfile(this, mProfile);
    /* TODO: At the moment we have no way to handle asynchronous PW input
     * Fixing will also allow to handle challenge/response authentication */
    if (mProfile.needUserPWInput(true) != 0) return START_NOT_STICKY;

    return START_STICKY;
  }
 public void userPause(boolean shouldBePaused) {
   if (mDeviceStateReceiver != null) mDeviceStateReceiver.userPause(shouldBePaused);
 }