226 lines
7.2 KiB
Java
Raw Normal View History

package org.fdroid.fdroid.localrepo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.os.IBinder;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
import android.support.annotation.Nullable;
import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
public class SwapManager {
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
private static final String TAG = "SwapState";
private static final String SHARED_PREFERENCES = "swap-state";
private static final String KEY_APPS_TO_SWAP = "appsToSwap";
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
private static SwapManager instance;
@NonNull
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
public static SwapManager load(@NonNull Context context) {
if (instance == null) {
SharedPreferences preferences = context.getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE);
Set<String> appsToSwap = deserializePackages(preferences.getString(KEY_APPS_TO_SWAP, ""));
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
instance = new SwapManager(context, appsToSwap);
}
return instance;
}
@NonNull
private final Context context;
@NonNull
private Set<String> appsToSwap;
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
private SwapManager(@NonNull Context context, @NonNull Set<String> appsToSwap) {
this.context = context.getApplicationContext();
this.appsToSwap = appsToSwap;
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
setupService();
}
/**
* Where relevant, the state of the swap process will be saved to disk using preferences.
* Note that this is not always useful, for example saving the "current wifi network" is
* bound to cause trouble when the user opens the swap process again and is connected to
* a different network.
*/
private SharedPreferences persistence() {
return context.getSharedPreferences(SHARED_PREFERENCES, Context.MODE_APPEND);
}
// ==========================================================
// Manage the current step
// ("Step" refers to the current view being shown in the UI)
// ==========================================================
public static final int STEP_INTRO = 1;
public static final int STEP_SELECT_APPS = 2;
public static final int STEP_JOIN_WIFI = 3;
public static final int STEP_SHOW_NFC = 4;
public static final int STEP_WIFI_QR = 5;
private @SwapStep int step = STEP_INTRO;
/**
* Current screen that the swap process is up to.
* Will be one of the SwapState.STEP_* values.
*/
@SwapStep
public int getStep() {
return step;
}
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
public SwapManager setStep(@SwapStep int step) {
this.step = step;
return this;
}
public @NonNull Set<String> getAppsToSwap() {
return appsToSwap;
}
/**
* Ensure that we don't get put into an incorrect state, by forcing people to pass valid
* states to setStep. Ideally this would be done by requiring an enum or something to
* be passed rather than in integer, however that is harder to persist on disk than an int.
* This is the same as, e.g. {@link Context#getSystemService(String)}
*/
@IntDef({STEP_INTRO, STEP_SELECT_APPS, STEP_JOIN_WIFI, STEP_SHOW_NFC, STEP_WIFI_QR})
@Retention(RetentionPolicy.SOURCE)
public @interface SwapStep {}
// ==========================================
// Remember apps user wants to swap
// ==========================================
private void persistAppsToSwap() {
persistence().edit().putString(KEY_APPS_TO_SWAP, serializePackages(appsToSwap)).commit();
}
/**
* Replacement for {@link android.content.SharedPreferences.Editor#putStringSet(String, Set)}
* which is only available in API >= 11.
* Package names are reverse-DNS-style, so they should only have alpha numeric values. Thus,
* this uses a comma as the separator.
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
* @see SwapManager#deserializePackages(String)
*/
private static String serializePackages(Set<String> packages) {
StringBuilder sb = new StringBuilder();
for (String pkg : packages) {
if (sb.length() > 0) {
sb.append(',');
}
sb.append(pkg);
}
return sb.toString();
}
/**
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
* @see SwapManager#deserializePackages(String)
*/
private static Set<String> deserializePackages(String packages) {
Set<String> set = new HashSet<>();
Collections.addAll(set, packages.split(","));
return set;
}
public void ensureFDroidSelected() {
String fdroid = context.getPackageName();
if (!hasSelectedPackage(fdroid)) {
selectPackage(fdroid);
}
}
public boolean hasSelectedPackage(String packageName) {
return appsToSwap.contains(packageName);
}
public void selectPackage(String packageName) {
appsToSwap.add(packageName);
persistAppsToSwap();
}
public void deselectPackage(String packageName) {
if (appsToSwap.contains(packageName)) {
appsToSwap.remove(packageName);
}
persistAppsToSwap();
}
// ==========================================
// Local repo stop/start/restart handling
// ==========================================
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
@Nullable
private SwapService service = null;
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
private void setupService() {
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder binder) {
Log.d(TAG, "Swap service connected, enabling SwapManager to communicate with SwapService.");
service = ((SwapService.Binder)binder).getService();
}
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
@Override
public void onServiceDisconnected(ComponentName className) {
Log.d(TAG, "Swap service disconnected");
service = null;
}
};
// The server should not be doing anything or occupying any (noticable) resources
// until we actually ask it to enable swapping. Therefore, we will start it nice and
// early so we don't have to wait until it is connected later.
Intent service = new Intent(context, SwapService.class);
if (context.bindService(service, serviceConnection, Context.BIND_AUTO_CREATE)) {
context.startService(service);
}
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
}
public void enableSwapping() {
if (service != null) {
service.enableSwapping();
} else {
Log.e(TAG, "Couldn't enable swap, because service was not running.");
}
}
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
public void disableSwapping() {
if (service != null) {
service.disableSwapping();
} else {
Log.e(TAG, "Couldn't disable swap, because service was not running.");
}
setStep(STEP_INTRO);
}
/**
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
* Handles checking if the {@link SwapService} is running, and only restarts it if it was running.
*/
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
public void restartIfEnabled() {
if (service != null) {
service.restartIfEnabled();
}
}
WIP: Refactoring swap service. Removed LocalRepoService, replaced with SwapService. Still TODO: Manage threads. Currently everything is called from the UI thread, which is a regression from the previous behaviour. I'd like to manage this so that the code interacting with the SwapManager doesn't need to bother itself with whether it is calling from the UI thread or not. The local repo service had many different methods and properties for dealing with starting and stopping various things (webserver, bonjour, in the future it will also need to know about bluetooth and Wifi AP). The SwapService handles this stuff by delegating to specific classes that are only responsible for one of these. Hopefully this will make the process of enabling and disabling swap repos easier to reason about. The local repo service was also stopped and started quite regularly. This meant it was up to the code making use of the service to know if it was running or not, and to enable it if required. The new SwapService is only started once (when the singleton SwapManager is created for the first time). It should not use any more resources, because it is a background service most the time, and it is responsible for moving itself to the foreground when required (the burden is not on the code consuming this service to know when to do this). By having the service running more often, it doesn't need to' continually figure out if it needs to register or unregister listeners for various properties (e.g. https enabled) or wifi broadcasts. The listeners can stay active, and do nothing once notified if swapping is not enabled. Moved the timeout timer (which cancels the swap service after 15 mins) into the SwapService, rather than being managed by the SwapWorkflowActivity. Seems more appropriate for the service to know to time itself out rather than the Activity, seeing as the Activity can die and get GC'ed while the service is still running. Finally, although there is nothing stopping code in F-Droid from talking to the service directly, it is now handled by the SwapManager singleton. This means that details such as using a Messenger or Handler object in order to communicate via arg1 and arg2 is no longer required, and instead methods with proper type signatures can be used. This is similar (but not exactly the same) to how Android system services work. That is, ask for a "Manager" object using getSystemService(), and then use that to perform functionality and query state via that object, which delegates to the service. Then we get the best of both worlds: * Reasonable and type safe method signatures * Services that are not tied to activity lifecycles, which persist beyond the closing of the swap activity.
2015-05-31 22:54:57 +10:00
public boolean isEnabled() {
return service != null && service.isEnabled();
}
}