diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index 96b55286db..eca527543c 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -37,6 +37,7 @@ import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin; import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin; +import info.nightscout.androidaps.plugins.constraints.storage.StorageConstraintPlugin; import info.nightscout.androidaps.plugins.general.actions.ActionsFragment; import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin; import info.nightscout.androidaps.plugins.general.food.FoodPlugin; @@ -175,6 +176,7 @@ public class MainApp extends Application { if (Config.OTHERPROFILES) pluginsList.add(LocalProfilePlugin.getPlugin()); pluginsList.add(TreatmentsPlugin.getPlugin()); if (Config.SAFETY) pluginsList.add(SafetyPlugin.getPlugin()); + if (Config.SAFETY) pluginsList.add(StorageConstraintPlugin.getPlugin()); if (Config.APS) pluginsList.add(ObjectivesPlugin.getPlugin()); pluginsList.add(SourceXdripPlugin.getPlugin()); pluginsList.add(SourceNSClientPlugin.getPlugin()); @@ -198,6 +200,7 @@ public class MainApp extends Application { pluginsList.add(DstHelperPlugin.getPlugin()); + ConfigBuilderPlugin.getPlugin().initialize(); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/storage/StorageConstraintPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/storage/StorageConstraintPlugin.java new file mode 100644 index 0000000000..91f92f6c2d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/storage/StorageConstraintPlugin.java @@ -0,0 +1,67 @@ +package info.nightscout.androidaps.plugins.constraints.storage; + +import android.os.Environment; +import android.os.StatFs; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.Constraint; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.PluginDescription; +import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.logging.L; + +/** + * Created by Rumen on 06.03.2019. + */ +public class StorageConstraintPlugin extends PluginBase implements ConstraintsInterface { + private static Logger log = LoggerFactory.getLogger(L.CONSTRAINTS); + static StorageConstraintPlugin plugin = null; + + public static StorageConstraintPlugin getPlugin() { + if (plugin == null) + plugin = new StorageConstraintPlugin(); + return plugin; + } + + public StorageConstraintPlugin() { + super(new PluginDescription() + .mainType(PluginType.CONSTRAINTS) + .neverVisible(true) + .alwaysEnabled(true) + .showInList(false) + .pluginName(R.string.storage) + ); + } + + /** + * Constraints interface + **/ + + @Override + public Constraint isClosedLoopAllowed(Constraint value) { + long diskfree = getAvailableInternalMemorySize(); + log.debug("Internal storage free (Mb):"+diskfree); + if (diskfree < 200) { + value.set(false, MainApp.gs(R.string.diskfull), this); + } + + return value; + } + + public static long getAvailableInternalMemorySize() { + File path = Environment.getDataDirectory(); + StatFs stat = new StatFs(path.getPath()); + long blockSize = stat.getBlockSizeLong(); + long blocksAvailable = stat.getAvailableBlocksLong(); + int size = 1048576; // blocksize of 1 Mb + return ((blocksAvailable * blockSize) / size); + } + +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e610b4af2c..032052ad1c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1312,7 +1312,8 @@ Dayligh Saving time Dayligh Saving time change in 24h or less Dayligh Saving time change in less than 3 hours - Closed loop diabled - + internal storage constraint + Free at least 200Mb from internal storage! Loop disabled! %1$d day %1$d days diff --git a/app/src/test/java/info/AAPSMocker.java b/app/src/test/java/info/AAPSMocker.java index f1ec982f9b..fc80b39e4d 100644 --- a/app/src/test/java/info/AAPSMocker.java +++ b/app/src/test/java/info/AAPSMocker.java @@ -104,6 +104,7 @@ public class AAPSMocker { when(MainApp.gs(R.string.profile_per_unit)).thenReturn("/U"); when(MainApp.gs(R.string.profile_carbs_per_unit)).thenReturn("g/U"); when(MainApp.gs(R.string.profile_ins_units_per_hout)).thenReturn("U/h"); + when(MainApp.gs(R.string.diskfull)).thenReturn("Free at least 200Mb from internal storage! Loop disabled!"); } public static MainApp mockMainApp() { diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/constraints/storage/StorageConstraintPluginTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/constraints/storage/StorageConstraintPluginTest.java new file mode 100644 index 0000000000..c9b2914b1c --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/plugins/constraints/storage/StorageConstraintPluginTest.java @@ -0,0 +1,53 @@ +package info.nightscout.androidaps.plugins.constraints.storage; +import junit.framework.Assert; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import info.AAPSMocker; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.Constraint; + +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.mock; + +/** + * Created by Rumen on 06.03.2019. + */ + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MainApp.class, StorageConstraintPlugin.class}) +public class StorageConstraintPluginTest extends StorageConstraintPlugin{ + + StorageConstraintPlugin storageConstraintPlugin; + + @Test + public void isLoopInvocationAllowedTest(){ + PowerMockito.mockStatic(StorageConstraintPlugin.class); + // Set free space under 200(Mb) to disable loop + when(StorageConstraintPlugin.getAvailableInternalMemorySize()).thenReturn(150L); + Constraint c = new Constraint<>(true); + c = storageConstraintPlugin.isClosedLoopAllowed(c); + Assert.assertEquals(true, c.getReasons().contains(MainApp.gs(R.string.diskfull))); + Assert.assertEquals(Boolean.FALSE, c.value()); + // Set free space over 200(Mb) to enable loop + when(StorageConstraintPlugin.getAvailableInternalMemorySize()).thenReturn(300L); + Constraint c2 = new Constraint<>(true); + c2 = storageConstraintPlugin.isClosedLoopAllowed(c2); + Assert.assertEquals(false, c2.getReasons().contains(MainApp.gs(R.string.diskfull))); + Assert.assertEquals(Boolean.TRUE, c2.value()); + } + + @Before + public void prepareMock() { + AAPSMocker.mockMainApp(); + AAPSMocker.mockStrings(); +// PowerMockito.mockStatic(Environment.class); + storageConstraintPlugin = StorageConstraintPlugin.getPlugin(); + } +}