Loading src/main/java/com/nextcloud/android/sso/api/AidlNetworkRequest.java +27 −5 Original line number Diff line number Diff line Loading @@ -51,7 +51,7 @@ public class AidlNetworkRequest extends NetworkRequest { */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { Log.v(TAG, "Nextcloud Single sign-on: onServiceConnected [" + Thread.currentThread().getName() + "]"); Log.v(TAG, "onServiceConnected [" + Thread.currentThread().getName() + "]"); mService = IInputStreamService.Stub.asInterface(service); mBound.set(true); Loading @@ -62,13 +62,14 @@ public class AidlNetworkRequest extends NetworkRequest { } public void onServiceDisconnected(ComponentName className) { Log.e(TAG, "Nextcloud Single sign-on: ServiceDisconnected"); Log.e(TAG, "ServiceDisconnected [" +className.toString() + "]"); // This is called when the connection with the service has been // unexpectedly disconnected -- that is, its process crashed. mService = null; mBound.set(false); if (!mDestroyed) { Log.d(TAG, "Reconnecting lost service connection"); connectApiWithBackoff(); } } Loading Loading @@ -115,6 +116,15 @@ public class AidlNetworkRequest extends NetworkRequest { } } public void reconnect() { if (mContext != null) { mContext.unbindService(mConnection); } else { Log.e(TAG, "Context was null, cannot unbind nextcloud single sign-on service connection!"); } // the callback "onServiceDisconnected" will trigger a reconnect automatically. No need to do anything here.. } private void waitForApi() throws NextcloudApiNotRespondingException { synchronized (mBound) { // If service is not bound yet.. wait Loading @@ -123,10 +133,20 @@ public class AidlNetworkRequest extends NetworkRequest { try { mBound.wait(10000); // wait up to 10 seconds // If api is still not bound after 10 seconds.. try reconnecting if(!mBound.get()) { /* // try one reconnect reconnect(); mBound.wait(10000); // wait up to 10 seconds // If api is still not bound after 10 seconds.. throw an exception if(!mBound.get()) { throw new NextcloudApiNotRespondingException(); } */ throw new NextcloudApiNotRespondingException(); } } catch (InterruptedException ex) { Log.e(TAG, "WaitForAPI failed", ex); } Loading @@ -143,8 +163,6 @@ public class AidlNetworkRequest extends NetworkRequest { * @throws Exception or SSOException */ public Response performNetworkRequestV2(NextcloudRequest request, InputStream requestBodyInputStream) throws Exception { ParcelFileDescriptor output = performAidlNetworkRequestV2(request, requestBodyInputStream); InputStream os = new ParcelFileDescriptor.AutoCloseInputStream(output); ExceptionResponse response = deserializeObjectV2(os); Loading Loading @@ -204,6 +222,10 @@ public class AidlNetworkRequest extends NetworkRequest { throw new NetworkOnMainThreadException(); } if(mDestroyed) { throw new IllegalStateException("Nextcloud API already destroyed. Please report this issue."); } // Wait for api to be initialized waitForApi(); Loading src/main/java/com/nextcloud/android/sso/api/NetworkRequest.java +5 −1 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ import android.os.Looper; import android.util.Log; import com.nextcloud.android.sso.aidl.NextcloudRequest; import com.nextcloud.android.sso.exceptions.NextcloudApiNotRespondingException; import com.nextcloud.android.sso.helper.ExponentialBackoff; import com.nextcloud.android.sso.model.SingleSignOnAccount; Loading Loading @@ -41,8 +42,11 @@ public abstract class NetworkRequest { protected abstract Response performNetworkRequestV2(NextcloudRequest request, InputStream requestBodyInputStream) throws Exception; protected void connectApiWithBackoff() { new ExponentialBackoff(1000, 10000, 2, 5, Looper.getMainLooper(), () -> { new ExponentialBackoff(1000, 5000, 2, 5, Looper.getMainLooper(), () -> { connect(mAccount.type); }, () -> { Log.e(TAG, "Unable to recover API"); stop(); }).start(); } Loading src/main/java/com/nextcloud/android/sso/helper/ExponentialBackoff.java +9 −3 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ public class ExponentialBackoff { private int mMaxRetries; private int mMultiplier; private final Runnable mRunnable; private final Runnable mFailedCallback; private final Handler mHandler; /** Loading Loading @@ -64,8 +65,9 @@ public class ExponentialBackoff { int multiplier, int maxRetries, @NonNull Looper looper, @NonNull Runnable runnable) { this(initialDelayMs, maximumDelayMs, multiplier, maxRetries, new Handler(looper), runnable); @NonNull Runnable runnable, @NonNull Runnable onErrorRunnable) { this(initialDelayMs, maximumDelayMs, multiplier, maxRetries, new Handler(looper), runnable, onErrorRunnable); } private ExponentialBackoff( Loading @@ -74,7 +76,8 @@ public class ExponentialBackoff { int multiplier, int maxRetries, @NonNull Handler handler, @NonNull Runnable runnable) { @NonNull Runnable runnable, @NonNull Runnable onErrorRunnable) { mRetryCounter = 0; mStartDelayMs = initialDelayMs; mMaximumDelayMs = maximumDelayMs; Loading @@ -82,6 +85,7 @@ public class ExponentialBackoff { mMaxRetries = maxRetries; mHandler = handler; mRunnable = new WrapperRunnable(runnable); mFailedCallback = onErrorRunnable; if(initialDelayMs <= 0) { throw new InvalidParameterException("initialDelayMs should not be less or equal to 0"); Loading @@ -99,12 +103,14 @@ public class ExponentialBackoff { public void stop() { mRetryCounter = 0; mHandlerAdapter.removeCallbacks(mRunnable); } /** Should call when the retry action has failed and we want to retry after a longer delay. */ private void notifyFailed() { if(mRetryCounter > mMaxRetries) { stop(); mFailedCallback.run(); } else { mRetryCounter++; long temp = Math.min( Loading Loading
src/main/java/com/nextcloud/android/sso/api/AidlNetworkRequest.java +27 −5 Original line number Diff line number Diff line Loading @@ -51,7 +51,7 @@ public class AidlNetworkRequest extends NetworkRequest { */ private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { Log.v(TAG, "Nextcloud Single sign-on: onServiceConnected [" + Thread.currentThread().getName() + "]"); Log.v(TAG, "onServiceConnected [" + Thread.currentThread().getName() + "]"); mService = IInputStreamService.Stub.asInterface(service); mBound.set(true); Loading @@ -62,13 +62,14 @@ public class AidlNetworkRequest extends NetworkRequest { } public void onServiceDisconnected(ComponentName className) { Log.e(TAG, "Nextcloud Single sign-on: ServiceDisconnected"); Log.e(TAG, "ServiceDisconnected [" +className.toString() + "]"); // This is called when the connection with the service has been // unexpectedly disconnected -- that is, its process crashed. mService = null; mBound.set(false); if (!mDestroyed) { Log.d(TAG, "Reconnecting lost service connection"); connectApiWithBackoff(); } } Loading Loading @@ -115,6 +116,15 @@ public class AidlNetworkRequest extends NetworkRequest { } } public void reconnect() { if (mContext != null) { mContext.unbindService(mConnection); } else { Log.e(TAG, "Context was null, cannot unbind nextcloud single sign-on service connection!"); } // the callback "onServiceDisconnected" will trigger a reconnect automatically. No need to do anything here.. } private void waitForApi() throws NextcloudApiNotRespondingException { synchronized (mBound) { // If service is not bound yet.. wait Loading @@ -123,10 +133,20 @@ public class AidlNetworkRequest extends NetworkRequest { try { mBound.wait(10000); // wait up to 10 seconds // If api is still not bound after 10 seconds.. try reconnecting if(!mBound.get()) { /* // try one reconnect reconnect(); mBound.wait(10000); // wait up to 10 seconds // If api is still not bound after 10 seconds.. throw an exception if(!mBound.get()) { throw new NextcloudApiNotRespondingException(); } */ throw new NextcloudApiNotRespondingException(); } } catch (InterruptedException ex) { Log.e(TAG, "WaitForAPI failed", ex); } Loading @@ -143,8 +163,6 @@ public class AidlNetworkRequest extends NetworkRequest { * @throws Exception or SSOException */ public Response performNetworkRequestV2(NextcloudRequest request, InputStream requestBodyInputStream) throws Exception { ParcelFileDescriptor output = performAidlNetworkRequestV2(request, requestBodyInputStream); InputStream os = new ParcelFileDescriptor.AutoCloseInputStream(output); ExceptionResponse response = deserializeObjectV2(os); Loading Loading @@ -204,6 +222,10 @@ public class AidlNetworkRequest extends NetworkRequest { throw new NetworkOnMainThreadException(); } if(mDestroyed) { throw new IllegalStateException("Nextcloud API already destroyed. Please report this issue."); } // Wait for api to be initialized waitForApi(); Loading
src/main/java/com/nextcloud/android/sso/api/NetworkRequest.java +5 −1 Original line number Diff line number Diff line Loading @@ -5,6 +5,7 @@ import android.os.Looper; import android.util.Log; import com.nextcloud.android.sso.aidl.NextcloudRequest; import com.nextcloud.android.sso.exceptions.NextcloudApiNotRespondingException; import com.nextcloud.android.sso.helper.ExponentialBackoff; import com.nextcloud.android.sso.model.SingleSignOnAccount; Loading Loading @@ -41,8 +42,11 @@ public abstract class NetworkRequest { protected abstract Response performNetworkRequestV2(NextcloudRequest request, InputStream requestBodyInputStream) throws Exception; protected void connectApiWithBackoff() { new ExponentialBackoff(1000, 10000, 2, 5, Looper.getMainLooper(), () -> { new ExponentialBackoff(1000, 5000, 2, 5, Looper.getMainLooper(), () -> { connect(mAccount.type); }, () -> { Log.e(TAG, "Unable to recover API"); stop(); }).start(); } Loading
src/main/java/com/nextcloud/android/sso/helper/ExponentialBackoff.java +9 −3 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ public class ExponentialBackoff { private int mMaxRetries; private int mMultiplier; private final Runnable mRunnable; private final Runnable mFailedCallback; private final Handler mHandler; /** Loading Loading @@ -64,8 +65,9 @@ public class ExponentialBackoff { int multiplier, int maxRetries, @NonNull Looper looper, @NonNull Runnable runnable) { this(initialDelayMs, maximumDelayMs, multiplier, maxRetries, new Handler(looper), runnable); @NonNull Runnable runnable, @NonNull Runnable onErrorRunnable) { this(initialDelayMs, maximumDelayMs, multiplier, maxRetries, new Handler(looper), runnable, onErrorRunnable); } private ExponentialBackoff( Loading @@ -74,7 +76,8 @@ public class ExponentialBackoff { int multiplier, int maxRetries, @NonNull Handler handler, @NonNull Runnable runnable) { @NonNull Runnable runnable, @NonNull Runnable onErrorRunnable) { mRetryCounter = 0; mStartDelayMs = initialDelayMs; mMaximumDelayMs = maximumDelayMs; Loading @@ -82,6 +85,7 @@ public class ExponentialBackoff { mMaxRetries = maxRetries; mHandler = handler; mRunnable = new WrapperRunnable(runnable); mFailedCallback = onErrorRunnable; if(initialDelayMs <= 0) { throw new InvalidParameterException("initialDelayMs should not be less or equal to 0"); Loading @@ -99,12 +103,14 @@ public class ExponentialBackoff { public void stop() { mRetryCounter = 0; mHandlerAdapter.removeCallbacks(mRunnable); } /** Should call when the retry action has failed and we want to retry after a longer delay. */ private void notifyFailed() { if(mRetryCounter > mMaxRetries) { stop(); mFailedCallback.run(); } else { mRetryCounter++; long temp = Math.min( Loading