Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Sensus.Android.Shared/AndroidSensusServiceHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ public AndroidSensusServiceHelper()
_userDeniedBluetoothEnable = false;
_wakeLock = (Application.Context.GetSystemService(global::Android.Content.Context.PowerService) as PowerManager).NewWakeLock(WakeLockFlags.Partial, "SENSUS");
_deviceId = Settings.Secure.GetString(Application.Context.ContentResolver, Settings.Secure.AndroidId);

Microsoft.AppCenter.AppCenter.SetUserId(_deviceId);
}

#region main activity
Expand Down
40 changes: 20 additions & 20 deletions Sensus.Android.Tests/Sensus.Android.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Xamarin.Forms.3.2.0.839982\build\netstandard2.0\Xamarin.Forms.props" Condition="Exists('..\packages\Xamarin.Forms.3.2.0.839982\build\netstandard2.0\Xamarin.Forms.props')" />
<Import Project="..\packages\Xamarin.Build.Download.0.4.11\build\Xamarin.Build.Download.props" Condition="Exists('..\packages\Xamarin.Build.Download.0.4.11\build\Xamarin.Build.Download.props')" />
Expand Down Expand Up @@ -52,6 +52,24 @@
<AndroidSupportedAbis>armeabi-v7a;arm64-v8a;x86</AndroidSupportedAbis>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.AppCenter, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AppCenter.1.14.0\lib\MonoAndroid403\Microsoft.AppCenter.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Analytics, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AppCenter.Analytics.1.14.0\lib\MonoAndroid403\Microsoft.AppCenter.Analytics.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Analytics.Android.Bindings, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AppCenter.Analytics.1.14.0\lib\MonoAndroid403\Microsoft.AppCenter.Analytics.Android.Bindings.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Android.Bindings, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AppCenter.1.14.0\lib\MonoAndroid403\Microsoft.AppCenter.Android.Bindings.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Crashes, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AppCenter.Crashes.1.14.0\lib\MonoAndroid403\Microsoft.AppCenter.Crashes.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Crashes.Android.Bindings, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AppCenter.Crashes.1.14.0\lib\MonoAndroid403\Microsoft.AppCenter.Crashes.Android.Bindings.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
Expand Down Expand Up @@ -304,24 +322,6 @@
<Reference Include="Xamarin.Azure.NotificationHubs.Android">
<HintPath>..\packages\Xamarin.Azure.NotificationHubs.Android.0.4.0\lib\MonoAndroid403\Xamarin.Azure.NotificationHubs.Android.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Android.Bindings">
<HintPath>..\packages\Microsoft.AppCenter.1.11.0\lib\MonoAndroid403\Microsoft.AppCenter.Android.Bindings.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter">
<HintPath>..\packages\Microsoft.AppCenter.1.11.0\lib\MonoAndroid403\Microsoft.AppCenter.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Analytics.Android.Bindings">
<HintPath>..\packages\Microsoft.AppCenter.Analytics.1.11.0\lib\MonoAndroid403\Microsoft.AppCenter.Analytics.Android.Bindings.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Analytics">
<HintPath>..\packages\Microsoft.AppCenter.Analytics.1.11.0\lib\MonoAndroid403\Microsoft.AppCenter.Analytics.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Crashes.Android.Bindings">
<HintPath>..\packages\Microsoft.AppCenter.Crashes.1.11.0\lib\MonoAndroid403\Microsoft.AppCenter.Crashes.Android.Bindings.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Crashes">
<HintPath>..\packages\Microsoft.AppCenter.Crashes.1.11.0\lib\MonoAndroid403\Microsoft.AppCenter.Crashes.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.12.0.1\lib\netstandard2.0\Newtonsoft.Json.dll</HintPath>
</Reference>
Expand Down Expand Up @@ -378,7 +378,7 @@
<Folder Include="Resources\mipmap-xhdpi\" />
<Folder Include="Resources\mipmap-xxhdpi\" />
<Folder Include="Resources\mipmap-xxxhdpi\" />
<Folder Include="Resources\drawable\" />
<Folder Include="Resources\drawable\" />
<Folder Include="Resources\values\" />
</ItemGroup>
<ItemGroup>
Expand Down
6 changes: 3 additions & 3 deletions Sensus.Android.Tests/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
<package id="Estimote.Android.Indoor" version="2.5.4.2" targetFramework="monoandroid90" />
<package id="Estimote.Android.Proximity" version="1.0.3" targetFramework="monoandroid90" />
<package id="FastAndroidCamera" version="2.0.0" targetFramework="monoandroid90" />
<package id="Microsoft.AppCenter" version="1.11.0" targetFramework="monoandroid90" />
<package id="Microsoft.AppCenter.Analytics" version="1.11.0" targetFramework="monoandroid90" />
<package id="Microsoft.AppCenter.Crashes" version="1.11.0" targetFramework="monoandroid90" />
<package id="Microsoft.AppCenter" version="1.14.0" targetFramework="monoandroid90" />
<package id="Microsoft.AppCenter.Analytics" version="1.14.0" targetFramework="monoandroid90" />
<package id="Microsoft.AppCenter.Crashes" version="1.14.0" targetFramework="monoandroid90" />
<package id="Newtonsoft.Json" version="12.0.1" targetFramework="monoandroid90" />
<package id="PCLCrypto" version="2.0.147" targetFramework="monoandroid81" />
<package id="PCLStorage" version="1.0.2" targetFramework="monoandroid90" />
Expand Down
38 changes: 19 additions & 19 deletions Sensus.Android/Sensus.Android.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,24 @@ Store. It is possible to run and debug this project on physical and virtual Andr
<JavaMaximumHeapSize>2G</JavaMaximumHeapSize>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.AppCenter, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AppCenter.1.14.0\lib\MonoAndroid403\Microsoft.AppCenter.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Analytics, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AppCenter.Analytics.1.14.0\lib\MonoAndroid403\Microsoft.AppCenter.Analytics.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Analytics.Android.Bindings, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AppCenter.Analytics.1.14.0\lib\MonoAndroid403\Microsoft.AppCenter.Analytics.Android.Bindings.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Android.Bindings, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AppCenter.1.14.0\lib\MonoAndroid403\Microsoft.AppCenter.Android.Bindings.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Crashes, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AppCenter.Crashes.1.14.0\lib\MonoAndroid403\Microsoft.AppCenter.Crashes.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Crashes.Android.Bindings, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AppCenter.Crashes.1.14.0\lib\MonoAndroid403\Microsoft.AppCenter.Crashes.Android.Bindings.dll</HintPath>
</Reference>
<Reference Include="Mono.Android" />
<Reference Include="System" />
<Reference Include="System.Core" />
Expand Down Expand Up @@ -301,24 +319,6 @@ Store. It is possible to run and debug this project on physical and virtual Andr
<Reference Include="Xamarin.Azure.NotificationHubs.Android">
<HintPath>..\packages\Xamarin.Azure.NotificationHubs.Android.0.5.0\lib\MonoAndroid403\Xamarin.Azure.NotificationHubs.Android.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Android.Bindings">
<HintPath>..\packages\Microsoft.AppCenter.1.11.0\lib\MonoAndroid403\Microsoft.AppCenter.Android.Bindings.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter">
<HintPath>..\packages\Microsoft.AppCenter.1.11.0\lib\MonoAndroid403\Microsoft.AppCenter.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Analytics.Android.Bindings">
<HintPath>..\packages\Microsoft.AppCenter.Analytics.1.11.0\lib\MonoAndroid403\Microsoft.AppCenter.Analytics.Android.Bindings.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Analytics">
<HintPath>..\packages\Microsoft.AppCenter.Analytics.1.11.0\lib\MonoAndroid403\Microsoft.AppCenter.Analytics.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Crashes.Android.Bindings">
<HintPath>..\packages\Microsoft.AppCenter.Crashes.1.11.0\lib\MonoAndroid403\Microsoft.AppCenter.Crashes.Android.Bindings.dll</HintPath>
</Reference>
<Reference Include="Microsoft.AppCenter.Crashes">
<HintPath>..\packages\Microsoft.AppCenter.Crashes.1.11.0\lib\MonoAndroid403\Microsoft.AppCenter.Crashes.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.12.0.1\lib\netstandard2.0\Newtonsoft.Json.dll</HintPath>
</Reference>
Expand Down Expand Up @@ -387,7 +387,7 @@ Store. It is possible to run and debug this project on physical and virtual Andr
<ItemGroup>
<AndroidAsset Include="Assets\README.txt" />
</ItemGroup>
<ItemGroup>
<ItemGroup>
<Folder Include="Resources\values-v21\" />
<Folder Include="Resources\layout\" />
</ItemGroup>
Expand Down
6 changes: 3 additions & 3 deletions Sensus.Android/packages.config
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
<package id="Estimote.Android.Proximity" version="1.0.3" targetFramework="monoandroid90" />
<package id="ExifLib.PCL" version="1.0.2-pre01" targetFramework="MonoAndroid60" />
<package id="FastAndroidCamera" version="2.0.0" targetFramework="monoandroid71" />
<package id="Microsoft.AppCenter" version="1.11.0" targetFramework="monoandroid90" />
<package id="Microsoft.AppCenter.Analytics" version="1.11.0" targetFramework="monoandroid90" />
<package id="Microsoft.AppCenter.Crashes" version="1.11.0" targetFramework="monoandroid90" />
<package id="Microsoft.AppCenter" version="1.14.0" targetFramework="monoandroid90" />
<package id="Microsoft.AppCenter.Analytics" version="1.14.0" targetFramework="monoandroid90" />
<package id="Microsoft.AppCenter.Crashes" version="1.14.0" targetFramework="monoandroid90" />
<package id="Microsoft.Bcl" version="1.1.10" targetFramework="MonoAndroid50" />
<package id="Microsoft.Bcl.Build" version="1.0.21" targetFramework="MonoAndroid44" />
<package id="Microsoft.CSharp" version="4.5.0" targetFramework="monoandroid81" />
Expand Down
122 changes: 121 additions & 1 deletion Sensus.Shared/DataStores/Local/FileLocalDataStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,16 @@ public class FileLocalDataStore : LocalDataStore, IClearableDataStore
/// </summary>
private const int DEFAULT_BUFFER_SIZE_BYTES = 4096;

/// <summary>
/// This is a default maximum local data storage that can be used before we start deleting the oldest data
/// </summary>
private const int DEFAULT_MAX_LOCAL_DATA_SIZE_MB = 2048;

/// <summary>
/// This is the default free storage percent that we maintain on the device before we start deleting the oldest data
/// </summary>
private const double DEFAULT_MIN_DEVICE_FREE_STORAGE_PERCENT = .20;

/// <summary>
/// File extension to use for JSON files.
/// </summary>
Expand Down Expand Up @@ -112,6 +122,8 @@ public class FileLocalDataStore : LocalDataStore, IClearableDataStore
private List<string> _pathsPreparedForRemote;
private List<string> _pathsUnpreparedForRemote;
private int _totalFilesPreparedForRemote;
private int _maxLocalDataSize;
private double _minDeviceFreeStoragePercent;

/// <summary>
/// Step 4: Transmission to the <see cref="Remote.RemoteDataStore"/>.
Expand Down Expand Up @@ -186,6 +198,50 @@ public int BufferSizeBytes
}
}

[EntryIntegerUiProperty("Maximum local storage size in MB", true, 3, true)]
public int MaxLocalDataSize
{
get
{
return _maxLocalDataSize;
}
set
{
if (value < _currentFileBufferSizeBytes / 1024)
{
_maxLocalDataSize = _currentFileBufferSizeBytes / 1024; //this should not be smaller than the buffer size
}
else
{
_maxLocalDataSize = value;
}
}
}

[EntryDoubleUiProperty("Minimum available device storage in Percent (0.00-1.00)", true, 4, true)]
public double MinDeviceFreeStoragePercent
{
get
{
return _minDeviceFreeStoragePercent;
}
set
{
if (value < 0)
{
_minDeviceFreeStoragePercent = 0.0;
}
else if (value > 1)
{
_minDeviceFreeStoragePercent = 1.0;
}
else
{
_minDeviceFreeStoragePercent = value;
}
}
}

/// <summary>
/// Whether or not to apply asymmetric-key encryption to data. If this is enabled, then you must either provide a public encryption
/// key to <see cref="Protocol.AsymmetricEncryptionPublicKey"/> or use an [authentication server](xref:authentication_servers).
Expand Down Expand Up @@ -279,6 +335,8 @@ public FileLocalDataStore()
_writeBufferedDataToFileTask = null;
_toWriteBuffer = new List<Datum>();
_bufferedDataHaveBeenWrittenToFile = new AutoResetEvent(false);
_maxLocalDataSize = DEFAULT_MAX_LOCAL_DATA_SIZE_MB;
_minDeviceFreeStoragePercent = DEFAULT_MIN_DEVICE_FREE_STORAGE_PERCENT;

// step 3: compressed, encrypted file
_compressionLevel = CompressionLevel.Optimal;
Expand Down Expand Up @@ -719,6 +777,11 @@ private double GetSizeMB()
return sizeMB;
}

private double GetAvailablePercent()
{
return SensusServiceHelper.GetAvailableStoragePercent();
}

public void Flush()
{
// there's a race condition between writing new data to the buffers and flushing them. enter an
Expand Down Expand Up @@ -905,6 +968,46 @@ public void Clear()
}
}

private void ReduceFileSizeToLimits()
{
List<string> pathsUnpreparedForRemote;

UpdatePathsPreparedForRemote();

while (_pathsPreparedForRemote.Count > 1 && GetSizeMB() > _maxLocalDataSize)
{
if(DeleteOldestPreparedFile() == false)
{
break;
}
}
while (_pathsPreparedForRemote.Count > 1 && GetAvailablePercent() < _minDeviceFreeStoragePercent)
{
if (DeleteOldestPreparedFile() == false)
{
break;
}
}

UpdatePathsPreparedForRemote();

}

private bool DeleteOldestPreparedFile()
{
lock (_pathsPreparedForRemote)
{
var toDelete = new DirectoryInfo(StorageDirectory).GetFiles("*.gz").Where(w => _pathsPreparedForRemote.Contains(w.FullName)).OrderByDescending(o => o.CreationTime).Select(s => s.FullName).FirstOrDefault();
if (toDelete != null)
{
File.Delete(toDelete);
_pathsPreparedForRemote.Remove(toDelete);
return true;
}
return false;
}
}

public override async Task<HealthTestResult> TestHealthAsync(List<AnalyticsTrackedEvent> events)
{
// retry file preparation for any unprepared paths
Expand All @@ -919,6 +1022,19 @@ public override async Task<HealthTestResult> TestHealthAsync(List<AnalyticsTrack
await PreparePathForRemoteAsync(pathUnpreparedForRemote, CancellationToken.None);
}


double startFileSize = GetSizeMB(); //TODO: This only gets prepared files, which i think it what we really care about. We could use SensusServiceHelper.GetDirectorySizeMB(StorageDirectory); if we wanted to include the currently processing file
double endFileSize = startFileSize;
double availablePercentage = GetAvailablePercent();
if (startFileSize > _maxLocalDataSize ||
availablePercentage < _minDeviceFreeStoragePercent)
{
ReduceFileSizeToLimits();
endFileSize = GetSizeMB();
availablePercentage = GetAvailablePercent();
}


HealthTestResult result = await base.TestHealthAsync(events);

string eventName = TrackedEvent.Health + ":" + GetType().Name;
Expand All @@ -929,7 +1045,11 @@ public override async Task<HealthTestResult> TestHealthAsync(List<AnalyticsTrack
{ "Percent Closed Files Prepared For Remote", Convert.ToString(_totalFilesPreparedForRemote.RoundToWholePercentageOf(_totalFilesClosed, 5)) },
{ "Percent Closed Files Written To Remote", Convert.ToString(_totalFilesWrittenToRemote.RoundToWholePercentageOf(_totalFilesClosed, 5)) },
{ "Paths Unprepared For Remote", Convert.ToString(_pathsUnpreparedForRemote.Count) },
{ "Prepared Files Size MB", Convert.ToString(Math.Round(GetSizeMB(), 0)) }
{ "Prepared Files Size MB", Convert.ToString(Math.Round(GetSizeMB(), 0)) },
{ "Maximum Files Size MB", Convert.ToString(_maxLocalDataSize) },
{ "Available Disk Space Percent", Convert.ToString(Math.Round(availablePercentage, 3)) },
{ "Minimum Disk Space Percent", Convert.ToString(Math.Round(_minDeviceFreeStoragePercent, 3)) },
{ "Amount Reduced MB", Convert.ToString(startFileSize-endFileSize) },
};

Analytics.TrackEvent(eventName, properties);
Expand Down
1 change: 1 addition & 0 deletions Sensus.Shared/DataStores/Local/LocalDataStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public abstract class LocalDataStore : DataStore
{
private bool _sizeTriggeredRemoteWriteRunning;
private bool _writeToRemote;
private int _maxLocalDataUsage;

private readonly object _sizeTriggeredRemoteWriteLocker = new object();

Expand Down
14 changes: 14 additions & 0 deletions Sensus.Shared/SensusServiceHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,20 @@ public static double GetFileSizeMB(params string[] paths)
});
}

public static double GetAvailableStoragePercent()
{
double totalFreeSpace = 0;
double totalSize = 0;
List<DriveInfo> drives = System.IO.DriveInfo.GetDrives().Where(w => w.IsReady == true && w.AvailableFreeSpace > 0).ToList();
foreach(var drive in drives)
{
totalFreeSpace += drive.TotalFreeSpace;
totalSize += drive.TotalSize;
}
var available = totalFreeSpace / totalSize;
return available;
}

/// <remarks>
/// For testing purposes only
/// </remarks>
Expand Down
Loading