From ab619f904d18bf4d72eafea11617833f209a4e7c Mon Sep 17 00:00:00 2001
From: str4d <str4d@mail.i2p>
Date: Thu, 17 Jul 2014 00:56:04 +0000
Subject: [PATCH] Reverted to Enum for State, make it Parcelable

Talked with zzz and did more research, the overhead of Enum is minimal compared
to the benefits it provides.
---
 .../net/i2p/android/router/MainActivity.java  | 18 +++----
 .../net/i2p/android/router/MainFragment.java  |  2 +-
 .../android/router/service/RouterService.java | 30 ++++++------
 .../android/router/service/IRouterState.aidl  |  3 +-
 .../router/service/IRouterStateCallback.aidl  |  4 +-
 .../net/i2p/android/router/service/State.aidl |  3 ++
 .../net/i2p/android/router/service/State.java | 49 ++++++++++++-------
 7 files changed, 65 insertions(+), 44 deletions(-)
 create mode 100644 client/src/main/aidl/net/i2p/android/router/service/State.aidl

diff --git a/app/src/main/java/net/i2p/android/router/MainActivity.java b/app/src/main/java/net/i2p/android/router/MainActivity.java
index d14a9da4e..973058f1a 100644
--- a/app/src/main/java/net/i2p/android/router/MainActivity.java
+++ b/app/src/main/java/net/i2p/android/router/MainActivity.java
@@ -108,9 +108,9 @@ public class MainActivity extends I2PActivityBase implements
                 if (mStateService.isStarted()) {
                     // Update for the current state.
                     Util.d("Fetching state.");
-                    int curState = mStateService.getState();
+                    State curState = mStateService.getState();
                     Message msg = mHandler.obtainMessage(STATE_MSG);
-                    msg.getData().putInt(MSG_DATA, curState);
+                    msg.getData().putParcelable(MSG_DATA, curState);
                     mHandler.sendMessage(msg);
                 } else {
                     Util.d("StateService not started yet");
@@ -206,9 +206,9 @@ public class MainActivity extends I2PActivityBase implements
                     mStateService.registerCallback(mStateCallback);
                     // Update for the current state.
                     Util.d("Fetching state.");
-                    int curState = mStateService.getState();
+                    State curState = mStateService.getState();
                     Message msg = mHandler.obtainMessage(STATE_MSG);
-                    msg.getData().putInt(MSG_DATA, curState);
+                    msg.getData().putParcelable(MSG_DATA, curState);
                     mHandler.sendMessage(msg);
                 } else {
                     // Unbind
@@ -239,9 +239,9 @@ public class MainActivity extends I2PActivityBase implements
          * NOT be running in our main thread like most other things -- so,
          * to update the UI, we need to use a Handler to hop over there.
          */
-        public void stateChanged(int newState) throws RemoteException {
+        public void stateChanged(State newState) throws RemoteException {
             Message msg = mHandler.obtainMessage(STATE_MSG);
-            msg.getData().putInt(MSG_DATA, newState);
+            msg.getData().putParcelable(MSG_DATA, newState);
             mHandler.sendMessage(msg);
         }
     };
@@ -250,13 +250,13 @@ public class MainActivity extends I2PActivityBase implements
     private static final String MSG_DATA = "state";
 
     private Handler mHandler = new Handler() {
-        private int lastRouterState = -1;
+        private State lastRouterState = null;
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
             case STATE_MSG:
-                int state = msg.getData().getInt(MSG_DATA);
-                if (lastRouterState == -1 || lastRouterState != state) {
+                State state = msg.getData().getParcelable(MSG_DATA);
+                if (lastRouterState == null || lastRouterState != state) {
                     if (mMainFragment == null)
                         mMainFragment = (MainFragment) getSupportFragmentManager().findFragmentById(R.id.main_fragment);
                     if (mMainFragment != null) {
diff --git a/app/src/main/java/net/i2p/android/router/MainFragment.java b/app/src/main/java/net/i2p/android/router/MainFragment.java
index b96d9f133..121778b9d 100644
--- a/app/src/main/java/net/i2p/android/router/MainFragment.java
+++ b/app/src/main/java/net/i2p/android/router/MainFragment.java
@@ -235,7 +235,7 @@ public class MainFragment extends I2PFragmentBase {
         }
     }
 
-    public void updateState(int newState) {
+    public void updateState(State newState) {
         final ImageView lightImage = (ImageView) getView().findViewById(R.id.main_lights);
         if (newState == State.INIT ||
                 newState == State.STOPPED ||
diff --git a/app/src/main/java/net/i2p/android/router/service/RouterService.java b/app/src/main/java/net/i2p/android/router/service/RouterService.java
index edb09eb0d..13a772ec4 100644
--- a/app/src/main/java/net/i2p/android/router/service/RouterService.java
+++ b/app/src/main/java/net/i2p/android/router/service/RouterService.java
@@ -37,7 +37,7 @@ public class RouterService extends Service {
     private RouterContext _context;
     private String _myDir;
     //private String _apkPath;
-    private int _state = State.INIT;
+    private State _state = State.INIT;
     private Thread _starterThread;
     private StatusBar _statusBar;
     private Notifications _notif;
@@ -63,7 +63,7 @@ public class RouterService extends Service {
     @Override
     public void onCreate() {
         mStartCalled = false;
-        int lastState = getSavedState();
+        State lastState = getSavedState();
         setState(State.INIT);
         Util.d(this + " onCreate called"
                 + " Saved state is: " + lastState
@@ -445,7 +445,7 @@ public class RouterService extends Service {
             return mStartCalled;
         }
 
-        public int getState() throws RemoteException {
+        public State getState() throws RemoteException {
             return _state;
         }
     };
@@ -481,8 +481,8 @@ public class RouterService extends Service {
     /**
      * debug
      */
-    public int getState() {
-        return _state;
+    public String getState() {
+        return _state.toString();
     }
 
     public boolean canManualStop() {
@@ -584,7 +584,7 @@ public class RouterService extends Service {
         public void handleMessage(Message msg) {
             switch (msg.what) {
             case STATE_MSG:
-                final int state = _state;
+                final State state = _state;
                 // Broadcast to all clients the new state.
                 final int N = mStateCallbacks.beginBroadcast();
                 for (int i = 0; i < N; i++) {
@@ -646,13 +646,13 @@ public class RouterService extends Service {
      */
     private class Stopper implements Runnable {
 
-        private final int nextState;
-        private final int stopState;
+        private final State nextState;
+        private final State stopState;
 
         /**
          * call holding statelock
          */
-        public Stopper(int next, int stop) {
+        public Stopper(State next, State stop) {
             nextState = next;
             stopState = stop;
             setState(next);
@@ -764,17 +764,17 @@ public class RouterService extends Service {
         }
     }
 
-    private int getSavedState() {
+    private State getSavedState() {
         SharedPreferences prefs = getSharedPreferences(SHARED_PREFS, 0);
+        String stateString = prefs.getString(LAST_STATE, State.INIT.toString());
         try {
-            return prefs.getInt(LAST_STATE, State.INIT);
-        } catch (ClassCastException e) {
-            // Only a problem for first run after upgrade from old Enum state
+            return State.valueOf(stateString);
+        } catch (IllegalArgumentException e) {
             return State.INIT;
         }
     }
 
-    private void setState(int s) {
+    private void setState(State s) {
         _state = s;
         saveState();
         mHandler.sendEmptyMessage(STATE_MSG);
@@ -786,7 +786,7 @@ public class RouterService extends Service {
     private boolean saveState() {
         SharedPreferences prefs = getSharedPreferences(SHARED_PREFS, 0);
         SharedPreferences.Editor edit = prefs.edit();
-        edit.putInt(LAST_STATE, _state);
+        edit.putString(LAST_STATE, _state.toString());
         return edit.commit();
     }
 }
diff --git a/client/src/main/aidl/net/i2p/android/router/service/IRouterState.aidl b/client/src/main/aidl/net/i2p/android/router/service/IRouterState.aidl
index 95cf3d636..92bc3f321 100644
--- a/client/src/main/aidl/net/i2p/android/router/service/IRouterState.aidl
+++ b/client/src/main/aidl/net/i2p/android/router/service/IRouterState.aidl
@@ -1,5 +1,6 @@
 package net.i2p.android.router.service;
 
+import net.i2p.android.router.service.State;
 import net.i2p.android.router.service.IRouterStateCallback;
 
 /**
@@ -28,6 +29,6 @@ interface IRouterState {
     /**
     * Get the state of the I2P router
     **/
-    int getState();
+    State getState();
 
 }
diff --git a/client/src/main/aidl/net/i2p/android/router/service/IRouterStateCallback.aidl b/client/src/main/aidl/net/i2p/android/router/service/IRouterStateCallback.aidl
index 20221b4c3..5158ce44e 100644
--- a/client/src/main/aidl/net/i2p/android/router/service/IRouterStateCallback.aidl
+++ b/client/src/main/aidl/net/i2p/android/router/service/IRouterStateCallback.aidl
@@ -1,5 +1,7 @@
 package net.i2p.android.router.service;
 
+import net.i2p.android.router.service.State;
+
 /**
  * Callback interface used to send synchronous notifications of the current
  * RouterService state back to registered clients. Note that this is a
@@ -9,5 +11,5 @@ oneway interface IRouterStateCallback {
     /**
      * Called when the state of the I2P router changes
      */
-    void stateChanged(int newState);
+    void stateChanged(in State newState);
 }
diff --git a/client/src/main/aidl/net/i2p/android/router/service/State.aidl b/client/src/main/aidl/net/i2p/android/router/service/State.aidl
new file mode 100644
index 000000000..193b35749
--- /dev/null
+++ b/client/src/main/aidl/net/i2p/android/router/service/State.aidl
@@ -0,0 +1,3 @@
+package net.i2p.android.router.service;
+
+parcelable State;
diff --git a/client/src/main/java/net/i2p/android/router/service/State.java b/client/src/main/java/net/i2p/android/router/service/State.java
index 597564358..469165966 100644
--- a/client/src/main/java/net/i2p/android/router/service/State.java
+++ b/client/src/main/java/net/i2p/android/router/service/State.java
@@ -1,30 +1,45 @@
 package net.i2p.android.router.service;
 
+import android.os.Parcel;
+import android.os.Parcelable;
+
 /**
- * Extracted from RouterService because Enums should be avoided on Android.
- * <p/>
- * https://developer.android.com/training/articles/memory.html#Overhead
+ * Extracted from RouterService.
  *
  * @author str4d
  * @since 0.9.14
  */
-public class State {
+public enum State implements Parcelable {
     // These states persist even if we died... Yuck, it causes issues.
-    public static final int INIT = 0;
-    public static final int WAITING = 1;
-    public static final int STARTING = 2;
-    public static final int RUNNING = 3;
-    public static final int ACTIVE = 4;
+    INIT, WAITING, STARTING, RUNNING, ACTIVE,
     // unplanned (router stopped itself), next: killSelf()
-    public static final int STOPPING = 5;
-    public static final int STOPPED = 6;
+    STOPPING, STOPPED,
     // button, don't kill service when stopped, stay in MANUAL_STOPPED
-    public static final int MANUAL_STOPPING = 7;
-    public static final int MANUAL_STOPPED = 8;
+    MANUAL_STOPPING, MANUAL_STOPPED,
     // button, DO kill service when stopped, next: killSelf()
-    public static final int MANUAL_QUITTING = 9;
-    public static final int MANUAL_QUITTED = 10;
+    MANUAL_QUITTING, MANUAL_QUITTED,
     // Stopped by listener (no network), next: WAITING (spin waiting for network)
-    public static final int NETWORK_STOPPING = 11;
-    public static final int NETWORK_STOPPED = 12;
+    NETWORK_STOPPING, NETWORK_STOPPED;
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(final Parcel dest, final int flags) {
+        dest.writeString(name());
+    }
+
+    public static final Creator<State> CREATOR = new Creator<State>() {
+        @Override
+        public State createFromParcel(final Parcel source) {
+            return State.valueOf(source.readString());
+        }
+
+        @Override
+        public State[] newArray(final int size) {
+            return new State[size];
+        }
+    };
 }
-- 
GitLab