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
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// Copyright 2014 The Rector & Visitors of the University of Virginia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using Sensus.Probes.Device;
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace Sensus.Android.Probes.Device
{
public class AndroidProcessorUtilizationProbe : ProcessorUtilizationProbe
{
private string _cmd;
protected override async Task InitializeAsync()
{
await base.InitializeAsync();

int pid = global::Android.OS.Process.MyPid();

//run the top terminal command -n 1 (only run 1 iteration)
//-b (use batch mode)
//-q (don't show the header info)
//-p {pid} (only return for the sensus)
//-o %CPU (only return the CPU%
//this is a different version of top than most of the documentation i found. The best thing to do is to run "top --help" on the device
_cmd = $"top -n 1 -b -q -p {pid} -o %CPU";//TODO: We could get mem% or process time from this command if we wanted using the follow in cmd $"top -n 1 -b -q -p {pid} -o %CPU,%MEM,TIME+"
}

protected override async Task StartListeningAsync()
{
while (Running)
{
await RecordUtilization(); //remove the await
await Task.Delay(MinDataStoreDelay.HasValue ? MinDataStoreDelay.Value.Milliseconds : 1000);
}
}

protected override Task StopListeningAsync()
{
return Task.CompletedTask;
}

//https://stackoverflow.com/questions/2467579/how-to-get-cpu-usage-statistics-on-android This shows the basic idea i used but i had to modify the command quite a bit
private async Task RecordUtilization()
{

try
{
Java.Lang.Process p = Java.Lang.Runtime.GetRuntime().Exec(_cmd);


var inputVal = await ReadStream(p.InputStream);
if(inputVal == null)
{
var errorOutput = await ReadStream(p.ErrorStream);
if(string.IsNullOrWhiteSpace(errorOutput) == false)
{
throw new NotSupportedException(errorOutput);
}
else
{
throw new NotSupportedException();
}
}

if(double.TryParse(inputVal.Trim(), out double cpuPercent) == false)
{
throw new InvalidDataException(inputVal + " cannot be converted into a double");
}

await StoreDatumAsync(new ProcessorUtilizationDatum(DateTimeOffset.UtcNow, cpuPercent));

}
catch (Exception exc)
{
SensusServiceHelper.Get().Logger.Log("Error getting CPU Utilization. msg:"+exc.Message, LoggingLevel.Normal, GetType());
}
}

private async Task<string> ReadStream(Stream s)
{
string rVal = null;
try
{
using (var streamReader = new StreamReader(s))
{
if (streamReader.EndOfStream == false)
{
rVal = await streamReader.ReadToEndAsync();
System.Diagnostics.Trace.Write(rVal);
}
}
}
finally
{
s.Close();
s.Dispose();
}
return rVal;
}


//The link in the issue didn't show cpu utilization but just the cpu hardware info. I left the code here if that info would would useful for you.
//https://stackoverflow.com/questions/46714396/how-to-find-cpu-load-of-any-android-device-programmatically
//private async Task GetProcessorHardwareInfo()
//{
// try
// {
// string holder = "";
// string[] DATA = { "/system/bin/cat", "/proc/cpuinfo" };
// Java.Lang.ProcessBuilder processBuilder = new Java.Lang.ProcessBuilder(DATA);
// Java.Lang.Process process = processBuilder.Start();
// using (var inputStream = process.InputStream)
// {
// using (var streamReader = new StreamReader(inputStream))
// {
// holder = await streamReader.ReadToEndAsync();
// }
// }
// }
// catch (Exception)
// {
// }
//}

}
}
1 change: 1 addition & 0 deletions Sensus.Android.Shared/Sensus.Android.Shared.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)Concurrent\MainConcurrent.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Context\AndroidSensusContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Probes\Device\AndroidProcessorUtilizationProbe.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Probes\Movement\AndroidGyroscopeProbe.cs" />
<Compile Include="$(MSBuildThisFileDirectory)UI\SliderInputEffect.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Callbacks\AndroidCallbackScheduler.cs" />
Expand Down
68 changes: 68 additions & 0 deletions Sensus.Shared/Probes/Device/ProcessorUtilizationDatum.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright 2014 The Rector & Visitors of the University of Virginia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using Sensus.Anonymization;
using Sensus.Anonymization.Anonymizers;
using Sensus.Probes.User.Scripts.ProbeTriggerProperties;

namespace Sensus.Probes.Device
{
public class ProcessorUtilizationDatum : Datum
{
private double _cpuPercent;

[DoubleProbeTriggerProperty]
[Anonymizable(null, typeof(DoubleRoundingTensAnonymizer), false)]
public double CpuPercent
{
get { return _cpuPercent; }
set { _cpuPercent = value; }
}

public override string DisplayDetail
{
get { return "Cpu Utilization: " + _cpuPercent +"%"; }
}

/// <summary>
/// Gets the string placeholder value, which is the CPU Pervent.
/// </summary>
/// <value>The string placeholder value.</value>
public override object StringPlaceholderValue
{
get
{
return _cpuPercent+ "%";
}
}

/// <summary>
/// For JSON deserialization.
/// </summary>
private ProcessorUtilizationDatum() { }

public ProcessorUtilizationDatum(DateTimeOffset timestamp, double cpuPercent)
: base(timestamp)
{
_cpuPercent = cpuPercent;
}

public override string ToString()
{
return base.ToString() + Environment.NewLine +
DisplayDetail;
}
}
}
105 changes: 105 additions & 0 deletions Sensus.Shared/Probes/Device/ProcessorUtilizationProbe.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright 2014 The Rector & Visitors of the University of Virginia
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Syncfusion.SfChart.XForms;

namespace Sensus.Probes.Device
{
/// <summary>
/// Provides the <see cref="ProcessorUtilizationDatum"/> readings.
/// </summary>
public abstract class ProcessorUtilizationProbe : ListeningProbe
{

[JsonIgnore]
protected override bool DefaultKeepDeviceAwake
{
get
{
return true;
}
}

[JsonIgnore]
protected override string DeviceAwakeWarning
{
get
{
return "This setting does not affect iOS. Android devices will use additional power to report all updates.";
}
}

[JsonIgnore]
protected override string DeviceAsleepWarning
{
get
{
return "This setting does not affect iOS. Android devices will sleep and pause updates.";
}
}

public sealed override string DisplayName
{
get { return "Processor Utilization"; }
}

public sealed override Type DatumType
{
get { return typeof(ProcessorUtilizationDatum); }
}

protected override async Task InitializeAsync()
{
await base.InitializeAsync();
}




protected override ChartSeries GetChartSeries()
{
throw new NotImplementedException();
}

protected override ChartDataPoint GetChartDataPointFromDatum(Datum datum)
{
return new ChartDataPoint(datum.Timestamp.LocalDateTime, (datum as ProcessorUtilizationDatum).CpuPercent);
}

protected override ChartAxis GetChartPrimaryAxis()
{
return new DateTimeAxis
{
Title = new ChartAxisTitle
{
Text = "Time"
}
};
}

protected override RangeAxisBase GetChartSecondaryAxis()
{
return new NumericalAxis
{
Title = new ChartAxisTitle
{
Text = "CPU Utilization (%)"
}
};
}
}
}
2 changes: 2 additions & 0 deletions Sensus.Shared/Sensus.Shared.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
<Compile Include="$(MSBuildThisFileDirectory)Probes\Context\HumidityProbe.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Probes\Context\SoundDatum.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Probes\Device\BatteryDatum.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Probes\Device\ProcessorUtilizationProbe.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Probes\Device\ProcessorUtilizationDatum.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Probes\Device\ScreenDatum.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Probes\Location\ProximityDatum.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Probes\Location\ProximityProbe.cs" />
Expand Down