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;
|
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 boolean shouldBeOn();
|
||||||
public void onStartRouterClicked();
|
public void onStartRouterClicked();
|
||||||
public boolean onStopRouterClicked();
|
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
|
@Override
|
||||||
@ -118,9 +124,15 @@ public class MainFragment extends I2PFragmentBase {
|
|||||||
updateOneShot();
|
updateOneShot();
|
||||||
checkFirstStart();
|
checkFirstStart();
|
||||||
} else {
|
} else {
|
||||||
|
if (mCallback.isGracefulShutdownInProgress()) {
|
||||||
if(mCallback.onStopRouterClicked()) {
|
if(mCallback.onStopRouterClicked()) {
|
||||||
updateOneShot();
|
updateOneShot();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if(mCallback.onGracefulShutdownClicked()) {
|
||||||
|
updateOneShot();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -197,6 +209,21 @@ public class MainFragment extends I2PFragmentBase {
|
|||||||
|
|
||||||
boolean isOn = mCallback.shouldBeOn();
|
boolean isOn = mCallback.shouldBeOn();
|
||||||
b.setChecked(isOn);
|
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) {
|
if (showOnOff && !isOn) {
|
||||||
// Sometimes the final state message from the RouterService
|
// Sometimes the final state message from the RouterService
|
||||||
@ -249,6 +276,7 @@ public class MainFragment extends I2PFragmentBase {
|
|||||||
newState == State.NETWORK_STOPPED) {
|
newState == State.NETWORK_STOPPED) {
|
||||||
lightImage.setImageResource(R.drawable.routerlogo_0);
|
lightImage.setImageResource(R.drawable.routerlogo_0);
|
||||||
} else if (newState == State.STARTING ||
|
} else if (newState == State.STARTING ||
|
||||||
|
newState == State.GRACEFUL_SHUTDOWN ||
|
||||||
newState == State.STOPPING ||
|
newState == State.STOPPING ||
|
||||||
newState == State.MANUAL_STOPPING ||
|
newState == State.MANUAL_STOPPING ||
|
||||||
newState == State.MANUAL_QUITTING ||
|
newState == State.MANUAL_QUITTING ||
|
||||||
|
@ -87,7 +87,7 @@ public class RouterService extends Service {
|
|||||||
Intent intent = new Intent(this, RouterService.class);
|
Intent intent = new Intent(this, RouterService.class);
|
||||||
intent.putExtra(EXTRA_RESTART, true);
|
intent.putExtra(EXTRA_RESTART, true);
|
||||||
onStartCommand(intent, 12345, 67890);
|
onStartCommand(intent, 12345, 67890);
|
||||||
} else if(lastState == State.MANUAL_QUITTING) {
|
} else if(lastState == State.MANUAL_QUITTING || lastState == State.GRACEFUL_SHUTDOWN) {
|
||||||
synchronized(_stateLock) {
|
synchronized(_stateLock) {
|
||||||
setState(State.MANUAL_QUITTED);
|
setState(State.MANUAL_QUITTED);
|
||||||
stopSelf(); // Die.
|
stopSelf(); // Die.
|
||||||
@ -343,7 +343,7 @@ public class RouterService extends Service {
|
|||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
RouterContext ctx = _context;
|
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();
|
Router router = ctx.router();
|
||||||
if(router.isAlive()) {
|
if(router.isAlive()) {
|
||||||
updateStatus(ctx);
|
updateStatus(ctx);
|
||||||
@ -472,7 +472,8 @@ public class RouterService extends Service {
|
|||||||
&& _state != State.STOPPING
|
&& _state != State.STOPPING
|
||||||
&& _state != State.MANUAL_STOPPING
|
&& _state != State.MANUAL_STOPPING
|
||||||
&& _state != State.MANUAL_QUITTING
|
&& _state != State.MANUAL_QUITTING
|
||||||
&& _state != State.NETWORK_STOPPING) {
|
&& _state != State.NETWORK_STOPPING
|
||||||
|
&& _state != State.GRACEFUL_SHUTDOWN) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
@ -486,11 +487,15 @@ public class RouterService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean canManualStop() {
|
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
|
* Stop and don't restart the router, but keep the service
|
||||||
|
*
|
||||||
|
* Apparently unused - see manualQuit()
|
||||||
*/
|
*/
|
||||||
public void manualStop() {
|
public void manualStop() {
|
||||||
Util.d("manualStop called"
|
Util.d("manualStop called"
|
||||||
@ -502,7 +507,8 @@ public class RouterService extends Service {
|
|||||||
if(_state == State.STARTING) {
|
if(_state == State.STARTING) {
|
||||||
_starterThread.interrupt();
|
_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");
|
_statusBar.replace(StatusBar.ICON_STOPPING, "Stopping I2P");
|
||||||
Thread stopperThread = new Thread(new Stopper(State.MANUAL_STOPPING, State.MANUAL_STOPPED));
|
Thread stopperThread = new Thread(new Stopper(State.MANUAL_STOPPING, State.MANUAL_STOPPED));
|
||||||
stopperThread.start();
|
stopperThread.start();
|
||||||
@ -523,7 +529,8 @@ public class RouterService extends Service {
|
|||||||
if(_state == State.STARTING) {
|
if(_state == State.STARTING) {
|
||||||
_starterThread.interrupt();
|
_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");
|
_statusBar.replace(StatusBar.ICON_STOPPING, "Stopping I2P");
|
||||||
Thread stopperThread = new Thread(new Stopper(State.MANUAL_QUITTING, State.MANUAL_QUITTED));
|
Thread stopperThread = new Thread(new Stopper(State.MANUAL_QUITTING, State.MANUAL_QUITTED));
|
||||||
stopperThread.start();
|
stopperThread.start();
|
||||||
@ -544,7 +551,8 @@ public class RouterService extends Service {
|
|||||||
if(_state == State.STARTING) {
|
if(_state == State.STARTING) {
|
||||||
_starterThread.interrupt();
|
_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");
|
_statusBar.replace(StatusBar.ICON_STOPPING, "Network disconnected, stopping I2P");
|
||||||
// don't change state, let the shutdown hook do it
|
// don't change state, let the shutdown hook do it
|
||||||
Thread stopperThread = new Thread(new Stopper(State.NETWORK_STOPPING, State.NETWORK_STOPPING));
|
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 ************
|
// ******** end methods accessed from Activities and Receivers ************
|
||||||
|
|
||||||
private static final int STATE_MSG = 1;
|
private static final int STATE_MSG = 1;
|
||||||
@ -631,7 +712,8 @@ public class RouterService extends Service {
|
|||||||
if(_state == State.STARTING) {
|
if(_state == State.STARTING) {
|
||||||
_starterThread.interrupt();
|
_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?
|
// should this be in a thread?
|
||||||
_statusBar.replace(StatusBar.ICON_SHUTTING_DOWN, "I2P is shutting down");
|
_statusBar.replace(StatusBar.ICON_SHUTTING_DOWN, "I2P is shutting down");
|
||||||
Thread stopperThread = new Thread(new Stopper(State.STOPPING, State.STOPPED));
|
Thread stopperThread = new Thread(new Stopper(State.STOPPING, State.STOPPED));
|
||||||
@ -708,7 +790,8 @@ public class RouterService extends Service {
|
|||||||
_starterThread.interrupt();
|
_starterThread.interrupt();
|
||||||
}
|
}
|
||||||
if(_state == State.WAITING || _state == State.STARTING
|
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);
|
setState(State.STOPPING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -750,7 +833,7 @@ public class RouterService extends Service {
|
|||||||
mStateCallbacks.kill();
|
mStateCallbacks.kill();
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
stopSelf();
|
stopSelf();
|
||||||
} else if(_state == State.MANUAL_QUITTING) {
|
} else if(_state == State.MANUAL_QUITTING || _state == State.GRACEFUL_SHUTDOWN) {
|
||||||
setState(State.MANUAL_QUITTED);
|
setState(State.MANUAL_QUITTED);
|
||||||
// Unregister all callbacks.
|
// Unregister all callbacks.
|
||||||
mStateCallbacks.kill();
|
mStateCallbacks.kill();
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
<string name="button_router_off">Long press to start I2P</string>
|
<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_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". -->
|
<!-- Character to indicate a client tunnel. Usually first letter of the word "client". -->
|
||||||
<string name="char_client_tunnel">C</string>
|
<string name="char_client_tunnel">C</string>
|
||||||
|
@ -19,7 +19,9 @@ public enum State implements Parcelable {
|
|||||||
// button, DO kill service when stopped, next: killSelf()
|
// button, DO kill service when stopped, next: killSelf()
|
||||||
MANUAL_QUITTING, MANUAL_QUITTED,
|
MANUAL_QUITTING, MANUAL_QUITTED,
|
||||||
// Stopped by listener (no network), next: WAITING (spin waiting for network)
|
// 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
|
@Override
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
|
Reference in New Issue
Block a user