My watch face needs access to heart rate sensor, and I would like to know whether there is a physical sensor present prior to asking for permission. According to documentation, I can do it in two ways:
private SensorManager mSensorManager;
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
List<Sensor> deviceSensors = mSensorManager.getSensorList(Sensor.TYPE_HEART_RATE);
or
boolean heartRateSensorEnabled = mSensorManager.getDefaultSensor(Sensor.TYPE_HEART_RATE) != null;
However, if permission is not granted (which is by default), I get empty sensor list and also no default sensor. That makes me force ask for permission even if it is meaningless (Sony SW3, for example, doesn't have the sensor). Is there a way to differentiate between "permission denied" and "no sensor present"?
Try looking into requestPermissions
https://developer.android.com/reference/android/support/v4/app/ActivityCompat.html#requestPermissions(android.app.Activity,java.lang.String[], int) method. It has callback ActivityCompat.OnRequestPermissionsResultCallback which returns if the permission is denied or not.
To check if sensor is present or not, try to use the code in this SO thread where he listed the sensors and looked for TYPE_HEART_RATE.
Related
I am currently experimenting a bit with Solana accounts and I am wondering if it is possible to change the owner of an account.
I am curious it is possible since the security of some programs are relying on this owner check, as explained here
I am also looking into the assign function and on how it works, but I was not able to make it work yet.
Am I misunderstanding something or just was not able to make it work?
Here the Python code is used:
tx = Transaction().add(
create_account(CreateAccountParams(
from_pubkey=attacker_keypair.public_key,
new_account_pubkey=account_keypair.public_key,
lamports=client.get_minimum_balance_for_rent_exemption(0)["result"],
space=0,
program_id=attacker_keypair.public_key,
))
)
send_and_confirm_tx(client, tx, attacker_keypair, account_keypair)
print('Sending 1st tx to program')
tx = Transaction().add(TransactionInstruction(
keys=[
AccountMeta(pubkey=account_keypair.public_key, is_signer=False, is_writable=False),
],
program_id=PROGRAM_ID,
))
send_and_confirm_tx(client, tx, attacker_keypair)
print('Sending 2nd tx to program')
tx = Transaction().add(assign(AssignParams(
account_pubkey=account_keypair.public_key,
program_id=attacker2_keypair.public_key
)))
send_and_confirm_tx(client, tx, account_keypair)
Error message is: InvalidAccountForFee
account_keypair was already assigned to attacker_keypair, so when you try to use it as the fee payer in 2nd tx, the runtime yells at you, since account_keypair can only have its lamports reduced by the program living at attacker_keypair. To quickly fix your current issue, you can do:
print('Sending 2nd tx to program')
tx = Transaction().add(assign(AssignParams(
account_pubkey=account_keypair.public_key,
program_id=attacker2_keypair.public_key
)))
send_and_confirm_tx(client, tx, attacker_keypair, account_keypair)
This will cause another problem however. account_keypair is already owned by attacker_keypair, so only a program deployed to attacker_keypair can reassign ownership of account_keypair. You can read up more on the Solana Account model at: https://docs.solana.com/developing/programming-model/accounts#ownership-and-assignment-to-programs
The part that's interesting to you is:
The owner is a program id. The runtime grants the program write access to the account if its id matches the owner. For the case of the System program, the runtime allows clients to transfer lamports and importantly assign account ownership, meaning changing the owner to a different program id. If an account is not owned by a program, the program is only permitted to read its data and credit the account.
This means that to reassign ownership, you need to write an on-chain program that reassigns the ownership to attacker2_keypair, deploy it to attacker_keypair, and then send a transaction containing an instruction to attacker_keypair.
Here are some example programs that perform the assign on the AccountInfo: https://github.com/solana-labs/solana/blob/85a2e599bbbf3d51f201167f921718e52c7ce59f/programs/bpf/rust/realloc/src/processor.rs#L54
I have an issue regarding the synchronisation of different agents.
So I have a shared context with a BaseAgent class as the tutorial suggested for the case where we have more than 1 agent type in the same context. Then I have 4 more agent classes which are children of the Base Agent Class. For each of them I have the necessary serialisable agent packages and in my model class I also have specific package receivers and providers for each one of them.
All those agents are sharing a discrete spatial projection of the form:
repast::SharedDiscreteSpace<BaseAgentClass, repast::WrapAroundBorders, repast::SimpleAdder< BaseAgentClass > >* discreteSpace;
Three of my 4 agent types can move around and I have implemented their moves. However, they can move from one process to another and I need to use the 4 synchronisation statements which were introduced in the RepastHPC tutorial HPC:D03, Step 02: Agents Moving in Space.
The thing however is that I am not certain how to actually synchronise them, since the agents would need their specific providers, receivers and serialisable packages in order to be copied into the other process correctly. I tried doing the following:
discreteGridSpace->balance();
repast::RepastProcess::instance()->synchronizeAgentStatus<BaseAgentClass, SpecificAgentPackage, SpecificAgentPackageProvider, SpecificAgentPackageReceiver>(context, *specificAgentProvider, *specificAgentProvider, *specificAgentReceiver);
repast::RepastProcess::instance()->synchronizeProjectionInfo<BaseAgentClass, SpecificAgentPackage, SpecificAgentPackageProvider, SpecificAgentPackageReceiver>(context, *specificAgentProvider, *specificAgentProvider, *specificAgentReceiver);
repast::RepastProcess::instance()->synchronizeAgentStates< SpecificAgentPackage, SpecificAgentPackageProvider, SpecificAgentPackageReceiver >(* specificAgentProvider, * specificAgentReceiver);
However, when running I get the following error:
===================================================================================
= BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES
= PID 3224 RUNNING AT Aleksandars-MBP
= EXIT CODE: 11
= CLEANING UP REMAINING PROCESSES
= YOU CAN IGNORE THE BELOW CLEANUP MESSAGES
===================================================================================
YOUR APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault: 11 (signal 11)
This typically refers to a problem with your application.
Please see the FAQ page for debugging suggestions
So I am not certain how to actually synchronise the agents for each specific agent type, since they are all sharing the same context and spatial projection with the BaseAgentClass.
Thank you for the help in advance!
The intention here is that you'd have a single package that can be used for all the agent types. For example, in the Zombies demo model, the package has entries for the agent id components, and also infected and infectionTime. These last two only apply to the Human agents and not to the Zombies.
The methods where you provide and receive content should check for the agent type and take the appropriate action. For example, in the Zombies Model we have
void ZombieObserver::provideContent(RelogoAgent* agent, std::vector<AgentPackage>& out) {
AgentId id = agent->getId();
AgentPackage content = { id.id(), id.startingRank(), id.agentType(), id.currentRank(), 0, false };
if (id.agentType() == humanType) {
Human* human = static_cast<Human*> (agent);
content.infected = human->infected();
content.infectionTime = human->infectionTime();
}
out.push_back(content);
}
Here you can see we fill the AgentPackage with some defaults for infected and infectionTime and then update those if the agent is of the Human type. This is a ReLogo style model, so some of the details might be different but hopefully it's clear that there is a single package type that can handle all the agent types, and that you use the agent type to distinguish between types in your provide methods.
In the VS2019 project template for C++/CX D3D12, the DisplayInformation::DisplayContentsInvalidated event (documented here) is subscribed and when this event fires, the code in the project template attempts to validate the D3D12 device. The criteria being used to validate is whether the default adapter has changed:
// This method is called in the event handler for the DisplayContentsInvalidated event.
void DX::DeviceResources::ValidateDevice()
{
// The D3D Device is no longer valid if the default adapter changed since the device
// was created or if the device has been removed.
// First, get the LUID for the default adapter from when the device was created.
DXGI_ADAPTER_DESC previousDesc;
{
ComPtr<IDXGIAdapter1> previousDefaultAdapter;
DX::ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, &previousDefaultAdapter));
DX::ThrowIfFailed(previousDefaultAdapter->GetDesc(&previousDesc));
}
// Next, get the information for the current default adapter.
DXGI_ADAPTER_DESC currentDesc;
{
ComPtr<IDXGIFactory4> currentDxgiFactory;
DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(¤tDxgiFactory)));
ComPtr<IDXGIAdapter1> currentDefaultAdapter;
DX::ThrowIfFailed(currentDxgiFactory->EnumAdapters1(0, ¤tDefaultAdapter));
DX::ThrowIfFailed(currentDefaultAdapter->GetDesc(¤tDesc));
}
// If the adapter LUIDs don't match, or if the device reports that it has been removed,
// a new D3D device must be created.
if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart ||
previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart ||
FAILED(m_d3dDevice->GetDeviceRemovedReason()))
{
m_deviceRemoved = true;
}
}
However, it seems to me that the default adapter may not be the elected adapter, as you can see in this code, because it ensures the adapter can create a D3D12 device before electing it, and this same check does not exist in the validation code above:
// This method acquires the first available hardware adapter that supports Direct3D 12.
// If no such adapter can be found, *ppAdapter will be set to nullptr.
void DX::DeviceResources::GetHardwareAdapter(IDXGIAdapter1** ppAdapter)
{
ComPtr<IDXGIAdapter1> adapter;
*ppAdapter = nullptr;
for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != m_dxgiFactory->EnumAdapters1(adapterIndex, &adapter); adapterIndex++)
{
DXGI_ADAPTER_DESC1 desc;
adapter->GetDesc1(&desc);
if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
{
// Don't select the Basic Render Driver adapter.
continue;
}
// Check to see if the adapter supports Direct3D 12, but don't create the
// actual device yet.
if (SUCCEEDED(D3D12CreateDevice(adapter.Get(), D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
{
break;
}
}
*ppAdapter = adapter.Detach();
}
Is this unintentionally relying on the default adapter being the elected adapter, or are there wider assumptions we can make based on the default adapter having changed?
What is the real meaning if DisplayInformation::DisplayContentsInvalidated? What is this telling me? Why does this suggest the device is possibly invalid? What are the cases where this event fires andthe device would or would not be invalid?
And since we are also checking for a DeviceRemovedReason here, are there cases where the default adapter doesn't change but the device was removed because of DisplayInformation::DisplayContentsInvalidated?
Do we even really need to handle this at all? What would happen if I just completely ignored this event and kept trying to render? Would I not end up handling whatever problem this event firing is indicating in the documented "device lost scenarios" per this document?
We are still investigating your question and get some information.
With regards to when the DisplayContentInvalidated Event will be triggered, it is typically invoked upon various activities including changing of the primary display or if the display configurations have changed in any other way. This would also include if there were certain types of issues occurring with the graphics, which this event should be able to be utilized to handle such situations.
With regards to the template, we ran some tests on our end and we indeed did see that the project uses the first adapter that it finds that can handle DirectX12 rather than an elected adapter. Upon further tests, we removed that particular check and found that the application does indeed continue to run as expected. The adapter may not be the one that was used to create the device at application startup. So indeed, this check does seem like it can potentially be ignored as indicated. However, having this event in the code might not hurt as it can provide the extra functionality should it be required for any situation.
Any other detailed information would likely be found in our documentation regarding this. However, it seems that the template is meant for demonstrating certain functionalities of DirextX12 and its various API’s so ignoring the DisplayContentInvalidated Event should typically not cause any issues.
My region is:
Region region = new Region("backgroundRegion", Identifier.parse("24DDF411-8CF1-440C87CD-E368DAF9C93E"), null, null);
When I start the program I get this message:
06-26 18:03:21.061 7394-7394/? D/BeaconReferenceApp: setting up background monitoring for beacons and power saving
But it doesn't enter in any didEnterRegion function
So, I removed this line: backgroundPowerSaver = new BackgroundPowerSaver(this);
And change scanning times, as it follows:
beaconManager.setBackgroundScanPeriod(1100l);
beaconManager.setBackgroundBetweenScanPeriod(10000l-1100l);
I checked my Beacon UUID and they are 24DDF411-8CF1-440C87CD-E368DAF9C93E
So what is wrong? Why the app doesn't go to the didEnterRegion function?
I already made it work to work with other than AltBeacons... (ranging function works ok!)
My final goal is to get current time when a beacon is discovered...
A few possibilities:
If you are already in the beacon region, you won't get a second callback until the beacon disappears (turn it off for 30 seconds or so, then turn it back on while the app is running.) Alternatively, you can look for a call do didDetermineStateForRegion which is always called when your app starts up, with a flag that tells you if you are inside or outside.
Make sure you have granted runtime permissions to location.
Make sure location is turned on for your phone in settings.
Make sure the beacon is transmitting that identifier using the Locate app https://play.google.com/store/apps/details?id=com.radiusnetworks.locate&hl=en
Make sure you have the proper BeaconParser configured. The question is tagged Eddystone, but shows an iBeacon or AltBeacon-style UUID as the first identifier. Do you have a custom beacon parser configured? What beacon type are you trying to detect?
Android wear 2.0 screen can be automatically locked right after it is taken off
and the heart rate app / watch face would not work when it is not worn.
I am wondering is there any way to get current wear worn state without starting a service to listen to wear activity?
I tried to get the heart rate sensor accuracy, but I don't think it is a good way because I can not always get the right result in this way immediately.
Is there any system or gms API to get a current worn state synchronously?
On watches with an off-body sensor (which lock immediately when not worn), you can check for the existence of the wakeup sensor TYPE_LOW_LATENCY_OFF_BODY_DETECT. This is only a public API in O+, but you can just use the actual value for N MR1 and below.
SensorManager sensorManager =
(SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
boolean hasSensor = sensorManger.getDefaultSensor(34, true /* wakeup */) != null;
On watches without an off-body sensor (which don't lock immediately), your best bet is probably some sort of activity recognition, though there don't seem to be any public off-body activities that can be detected by Google APIs (see here).