propagate from branch 'i2p.android.base' (head 473e458dab49137f8211dcad60554cd90078807d)
to branch 'i2p.android.base.zzz.graceful' (head 57a30f761ea3d230301347dbb8b79bd3540f97a2)
This commit is contained in:
@ -315,4 +315,32 @@ public class MainActivity extends I2PActivityBase implements
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @since 0.9.18 */
|
||||
public boolean isGracefulShutdownInProgress() {
|
||||
RouterService svc = _routerService;
|
||||
return svc != null && svc.isGracefulShutdownInProgress();
|
||||
}
|
||||
|
||||
/** @since 0.9.18 */
|
||||
public boolean onGracefulShutdownClicked() {
|
||||
RouterService svc = _routerService;
|
||||
if(svc != null && _isBound) {
|
||||
setPref(PREF_AUTO_START, false);
|
||||
svc.gracefulShutdown();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @since 0.9.18 */
|
||||
public boolean onCancelGracefulShutdownClicked() {
|
||||
RouterService svc = _routerService;
|
||||
if(svc != null && _isBound) {
|
||||
setPref(PREF_AUTO_START, false);
|
||||
svc.cancelGracefulShutdown();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,12 @@ public class MainFragment extends I2PFragmentBase {
|
||||
public boolean shouldBeOn();
|
||||
public void onStartRouterClicked();
|
||||
public boolean onStopRouterClicked();
|
||||
/** @since 0.9.18 */
|
||||
public boolean isGracefulShutdownInProgress();
|
||||
/** @since 0.9.18 */
|
||||
public boolean onGracefulShutdownClicked();
|
||||
/** @since 0.9.18 */
|
||||
public boolean onCancelGracefulShutdownClicked();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -118,8 +124,14 @@ public class MainFragment extends I2PFragmentBase {
|
||||
updateOneShot();
|
||||
checkFirstStart();
|
||||
} else {
|
||||
if(mCallback.onStopRouterClicked()) {
|
||||
updateOneShot();
|
||||
if (mCallback.isGracefulShutdownInProgress()) {
|
||||
if(mCallback.onStopRouterClicked()) {
|
||||
updateOneShot();
|
||||
}
|
||||
} else {
|
||||
if(mCallback.onGracefulShutdownClicked()) {
|
||||
updateOneShot();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -197,6 +209,21 @@ public class MainFragment extends I2PFragmentBase {
|
||||
|
||||
boolean isOn = mCallback.shouldBeOn();
|
||||
b.setChecked(isOn);
|
||||
if (isOn && mCallback.isGracefulShutdownInProgress()) {
|
||||
RouterContext ctx = getRouterContext();
|
||||
if (ctx != null) {
|
||||
// TODO
|
||||
// Don't change text on this button... hide it,
|
||||
// and add two more buttons, one for cancel and one for shutdown immediately.
|
||||
long ms = ctx.router().getShutdownTimeRemaining();
|
||||
if (ms > 1000) {
|
||||
b.setTextOn(getActivity().getResources().getString(R.string.button_router_graceful,
|
||||
DataHelper.formatDuration(ms)));
|
||||
} else {
|
||||
b.setTextOn("Stopping I2P");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showOnOff && !isOn) {
|
||||
// Sometimes the final state message from the RouterService
|
||||
@ -249,6 +276,7 @@ public class MainFragment extends I2PFragmentBase {
|
||||
newState == State.NETWORK_STOPPED) {
|
||||
lightImage.setImageResource(R.drawable.routerlogo_0);
|
||||
} else if (newState == State.STARTING ||
|
||||
newState == State.GRACEFUL_SHUTDOWN ||
|
||||
newState == State.STOPPING ||
|
||||
newState == State.MANUAL_STOPPING ||
|
||||
newState == State.MANUAL_QUITTING ||
|
||||
|
@ -87,7 +87,7 @@ public class RouterService extends Service {
|
||||
Intent intent = new Intent(this, RouterService.class);
|
||||
intent.putExtra(EXTRA_RESTART, true);
|
||||
onStartCommand(intent, 12345, 67890);
|
||||
} else if(lastState == State.MANUAL_QUITTING) {
|
||||
} else if(lastState == State.MANUAL_QUITTING || lastState == State.GRACEFUL_SHUTDOWN) {
|
||||
synchronized(_stateLock) {
|
||||
setState(State.MANUAL_QUITTED);
|
||||
stopSelf(); // Die.
|
||||
@ -343,7 +343,7 @@ public class RouterService extends Service {
|
||||
|
||||
public void run() {
|
||||
RouterContext ctx = _context;
|
||||
if(ctx != null && (_state == State.RUNNING || _state == State.ACTIVE)) {
|
||||
if(ctx != null && (_state == State.RUNNING || _state == State.ACTIVE || _state == State.GRACEFUL_SHUTDOWN)) {
|
||||
Router router = ctx.router();
|
||||
if(router.isAlive()) {
|
||||
updateStatus(ctx);
|
||||
@ -472,7 +472,8 @@ public class RouterService extends Service {
|
||||
&& _state != State.STOPPING
|
||||
&& _state != State.MANUAL_STOPPING
|
||||
&& _state != State.MANUAL_QUITTING
|
||||
&& _state != State.NETWORK_STOPPING) {
|
||||
&& _state != State.NETWORK_STOPPING
|
||||
&& _state != State.GRACEFUL_SHUTDOWN) {
|
||||
return null;
|
||||
}
|
||||
return rv;
|
||||
@ -486,11 +487,15 @@ public class RouterService extends Service {
|
||||
}
|
||||
|
||||
public boolean canManualStop() {
|
||||
return _state == State.WAITING || _state == State.STARTING || _state == State.RUNNING || _state == State.ACTIVE;
|
||||
return _state == State.WAITING || _state == State.STARTING ||
|
||||
_state == State.RUNNING || _state == State.ACTIVE ||
|
||||
_state == State.GRACEFUL_SHUTDOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop and don't restart the router, but keep the service
|
||||
*
|
||||
* Apparently unused - see manualQuit()
|
||||
*/
|
||||
public void manualStop() {
|
||||
Util.d("manualStop called"
|
||||
@ -502,7 +507,8 @@ public class RouterService extends Service {
|
||||
if(_state == State.STARTING) {
|
||||
_starterThread.interrupt();
|
||||
}
|
||||
if(_state == State.STARTING || _state == State.RUNNING || _state == State.ACTIVE) {
|
||||
if(_state == State.STARTING || _state == State.RUNNING ||
|
||||
_state == State.ACTIVE || _state == State.GRACEFUL_SHUTDOWN) {
|
||||
_statusBar.replace(StatusBar.ICON_STOPPING, "Stopping I2P");
|
||||
Thread stopperThread = new Thread(new Stopper(State.MANUAL_STOPPING, State.MANUAL_STOPPED));
|
||||
stopperThread.start();
|
||||
@ -523,7 +529,8 @@ public class RouterService extends Service {
|
||||
if(_state == State.STARTING) {
|
||||
_starterThread.interrupt();
|
||||
}
|
||||
if(_state == State.STARTING || _state == State.RUNNING || _state == State.ACTIVE) {
|
||||
if(_state == State.STARTING || _state == State.RUNNING ||
|
||||
_state == State.ACTIVE || _state == State.GRACEFUL_SHUTDOWN) {
|
||||
_statusBar.replace(StatusBar.ICON_STOPPING, "Stopping I2P");
|
||||
Thread stopperThread = new Thread(new Stopper(State.MANUAL_QUITTING, State.MANUAL_QUITTED));
|
||||
stopperThread.start();
|
||||
@ -544,7 +551,8 @@ public class RouterService extends Service {
|
||||
if(_state == State.STARTING) {
|
||||
_starterThread.interrupt();
|
||||
}
|
||||
if(_state == State.STARTING || _state == State.RUNNING || _state == State.ACTIVE) {
|
||||
if(_state == State.STARTING || _state == State.RUNNING ||
|
||||
_state == State.ACTIVE || _state == State.GRACEFUL_SHUTDOWN) {
|
||||
_statusBar.replace(StatusBar.ICON_STOPPING, "Network disconnected, stopping I2P");
|
||||
// don't change state, let the shutdown hook do it
|
||||
Thread stopperThread = new Thread(new Stopper(State.NETWORK_STOPPING, State.NETWORK_STOPPING));
|
||||
@ -572,6 +580,79 @@ public class RouterService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Graceful Shutdown
|
||||
*
|
||||
* @since 0.9.18
|
||||
*/
|
||||
public boolean isGracefulShutdownInProgress() {
|
||||
if (_state == State.GRACEFUL_SHUTDOWN) {
|
||||
RouterContext ctx = _context;
|
||||
return ctx != null && ctx.router().gracefulShutdownInProgress();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Graceful Shutdown
|
||||
*
|
||||
* @since 0.9.18
|
||||
*/
|
||||
public void gracefulShutdown() {
|
||||
Util.d("gracefulShutdown called"
|
||||
+ " Current state is: " + _state);
|
||||
synchronized(_stateLock) {
|
||||
if(!canManualStop()) {
|
||||
return;
|
||||
}
|
||||
if(_state == State.STARTING || _state == State.WAITING) {
|
||||
manualQuit();
|
||||
return;
|
||||
}
|
||||
if(_state == State.RUNNING || _state == State.ACTIVE) {
|
||||
RouterContext ctx = _context;
|
||||
if(ctx != null && ctx.router().isAlive()) {
|
||||
int part = ctx.tunnelManager().getParticipatingCount();
|
||||
if(part <= 0) {
|
||||
manualQuit();
|
||||
} else {
|
||||
ctx.router().shutdownGracefully();
|
||||
long ms = ctx.router().getShutdownTimeRemaining();
|
||||
if (ms > 1000) {
|
||||
_statusBar.replace(StatusBar.ICON_STOPPING, "Stopping I2P in " + DataHelper.formatDuration(ms));
|
||||
} else {
|
||||
_statusBar.replace(StatusBar.ICON_STOPPING, "Stopping I2P");
|
||||
}
|
||||
setState(State.GRACEFUL_SHUTDOWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel Graceful Shutdown
|
||||
*
|
||||
* @since 0.9.18
|
||||
*/
|
||||
public void cancelGracefulShutdown() {
|
||||
Util.d("cancelGracefulShutdown called"
|
||||
+ " Current state is: " + _state);
|
||||
synchronized(_stateLock) {
|
||||
if(_state != State.GRACEFUL_SHUTDOWN) {
|
||||
return;
|
||||
}
|
||||
RouterContext ctx = _context;
|
||||
if(ctx != null && ctx.router().isAlive()) {
|
||||
ctx.router().cancelGracefulShutdown();
|
||||
_statusBar.replace(StatusBar.ICON_RUNNING, "Shutdown cancelled");
|
||||
setState(State.RUNNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ******** end methods accessed from Activities and Receivers ************
|
||||
|
||||
private static final int STATE_MSG = 1;
|
||||
@ -631,7 +712,8 @@ public class RouterService extends Service {
|
||||
if(_state == State.STARTING) {
|
||||
_starterThread.interrupt();
|
||||
}
|
||||
if(_state == State.STARTING || _state == State.RUNNING || _state == State.ACTIVE) {
|
||||
if(_state == State.STARTING || _state == State.RUNNING ||
|
||||
_state == State.ACTIVE || _state == State.GRACEFUL_SHUTDOWN) {
|
||||
// should this be in a thread?
|
||||
_statusBar.replace(StatusBar.ICON_SHUTTING_DOWN, "I2P is shutting down");
|
||||
Thread stopperThread = new Thread(new Stopper(State.STOPPING, State.STOPPED));
|
||||
@ -708,7 +790,8 @@ public class RouterService extends Service {
|
||||
_starterThread.interrupt();
|
||||
}
|
||||
if(_state == State.WAITING || _state == State.STARTING
|
||||
|| _state == State.RUNNING || _state == State.ACTIVE) {
|
||||
|| _state == State.RUNNING || _state == State.ACTIVE
|
||||
|| _state == State.GRACEFUL_SHUTDOWN) {
|
||||
setState(State.STOPPING);
|
||||
}
|
||||
}
|
||||
@ -750,7 +833,7 @@ public class RouterService extends Service {
|
||||
mStateCallbacks.kill();
|
||||
stopForeground(true);
|
||||
stopSelf();
|
||||
} else if(_state == State.MANUAL_QUITTING) {
|
||||
} else if(_state == State.MANUAL_QUITTING || _state == State.GRACEFUL_SHUTDOWN) {
|
||||
setState(State.MANUAL_QUITTED);
|
||||
// Unregister all callbacks.
|
||||
mStateCallbacks.kill();
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
<string name="button_router_off">Long press to start I2P</string>
|
||||
<string name="button_router_on">I2P is running (long press to stop)</string>
|
||||
<string name="button_router_graceful">I2P is shutting down in %s (long press to stop immediately)</string>
|
||||
|
||||
<!-- Character to indicate a client tunnel. Usually first letter of the word "client". -->
|
||||
<string name="char_client_tunnel">C</string>
|
||||
@ -227,4 +228,4 @@
|
||||
<string name="logs_copied_to_clipboard">Logs copied to clipboard</string>
|
||||
|
||||
<string name="label_browser_configuration">Browser configuration</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
@ -19,7 +19,9 @@ public enum State implements Parcelable {
|
||||
// button, DO kill service when stopped, next: killSelf()
|
||||
MANUAL_QUITTING, MANUAL_QUITTED,
|
||||
// Stopped by listener (no network), next: WAITING (spin waiting for network)
|
||||
NETWORK_STOPPING, NETWORK_STOPPED;
|
||||
NETWORK_STOPPING, NETWORK_STOPPED,
|
||||
/** @since 0.9.18 */
|
||||
GRACEFUL_SHUTDOWN;
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
|
Reference in New Issue
Block a user