Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
A simple sample that covers the basic usage for the PIO APIs. Change-Id: I56789ce84b7f167be832b6e4a7ff4205d833837c
- Loading branch information
0 parents
commit 0dd5926
Showing
17 changed files
with
688 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
*.iml | ||
.gradle | ||
local.properties | ||
.idea | ||
.DS_Store | ||
build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
Simple example of Brillo Peripheral I/O APIs | ||
============================================ | ||
|
||
This Brillo app runs basic code that exercises the PIO APIs. There is a set of API samples that | ||
can be "browsed" and executed by clicking on onboard buttons. | ||
|
||
Pre-requisites | ||
-------------- | ||
|
||
- Intel Edison | ||
- Brillo 2.0 | ||
|
||
|
||
Build and install | ||
================= | ||
|
||
1. Plug your Intel Edison board to your computer via USB | ||
2. Click on "Run" in Android Studio or use the command line: `./gradlew installDebug` | ||
|
||
|
||
Run | ||
=== | ||
|
||
Press the "RM" button on the Intel Edison to change from one task to another, and then press the | ||
"PWR" button to execute the selected task. The selected task will be printed on | ||
logcat (`adb logcat`). | ||
|
||
|
||
License | ||
------- | ||
|
||
Copyright 2016 The Android Open Source Project, Inc. | ||
|
||
Licensed to the Apache Software Foundation (ASF) under one or more contributor | ||
license agreements. See the NOTICE file distributed with this work for | ||
additional information regarding copyright ownership. The ASF licenses this | ||
file to you 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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
apply plugin: 'com.android.application' | ||
|
||
android { | ||
compileSdkVersion 23 | ||
buildToolsVersion '24.0.0-rc4' | ||
|
||
defaultConfig { | ||
applicationId "com.google.samples.mysample" | ||
minSdkVersion 21 | ||
targetSdkVersion 22 | ||
versionCode 1 | ||
versionName "1.0" | ||
jackOptions { | ||
enabled true | ||
} | ||
} | ||
buildTypes { | ||
debug { | ||
multiDexEnabled true | ||
} | ||
release { | ||
multiDexEnabled true | ||
minifyEnabled false | ||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' | ||
} | ||
} | ||
compileOptions { | ||
sourceCompatibility JavaVersion.VERSION_1_8 | ||
targetCompatibility JavaVersion.VERSION_1_8 | ||
} | ||
} | ||
|
||
dependencies { | ||
compile fileTree(dir: 'libs', include: ['*.jar']) | ||
testCompile 'junit:junit:4.12' | ||
} |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Add project specific ProGuard rules here. | ||
# By default, the flags in this file are appended to flags specified | ||
# in /usr/local/google/home/stammt/Android/Sdk/tools/proguard/proguard-android.txt | ||
# You can edit the include path and order by changing the proguardFiles | ||
# directive in build.gradle. | ||
# | ||
# For more details, see | ||
# http://developer.android.com/guide/developing/tools/proguard.html | ||
|
||
# Add any project specific keep options here: | ||
|
||
# If your project uses WebView with JS, uncomment the following | ||
# and specify the fully qualified class name to the JavaScript interface | ||
# class: | ||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview { | ||
# public *; | ||
#} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" | ||
package="com.google.samples.simplepio"> | ||
|
||
<application | ||
android:allowBackup="true" | ||
android:icon="@android:drawable/sym_def_app_icon" | ||
android:label="@string/app_name"> | ||
<service | ||
android:name="com.google.samples.simplepio.SimplePIOService" | ||
android:exported="true" | ||
android:permission="android.permission.BIND_HEADLESS_SERVICE" | ||
> | ||
<intent-filter> | ||
<action android:name="android.service.headless.HomeService" /> | ||
<category android:name="android.intent.category.DEFAULT" /> | ||
</intent-filter> | ||
</service> | ||
|
||
</application> | ||
|
||
|
||
</manifest> |
89 changes: 89 additions & 0 deletions
89
app/src/main/java/com/google/samples/simplepio/SimplePIOService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package com.google.samples.simplepio; | ||
|
||
import android.os.Handler; | ||
import android.os.HandlerThread; | ||
import android.service.headless.HomeService; | ||
import android.util.Log; | ||
import android.view.InputEvent; | ||
import android.view.KeyEvent; | ||
|
||
import com.google.samples.simplepio.task.GPIOTask; | ||
import com.google.samples.simplepio.task.LEDTask; | ||
|
||
/** | ||
* Simple {@link HomeService} that executes {@link Runnable} in a separate thread. | ||
* | ||
* When certain input events (Intel Edison onboard PWR and RM buttons) are received, | ||
* this class cycles through a list of tasks ({@link Runnable}) and schedules the selected task | ||
* to execute in a separate thread. | ||
*/ | ||
public class SimplePIOService extends HomeService { | ||
public static final String TAG = "SimplePIOService"; | ||
|
||
private static final int BUTTON_EDISON_RM_KEYCODE = 148; | ||
private static final int BUTTON_EDISON_PWR_KEYCODE = 116; | ||
|
||
private HandlerThread mRunnerThread; | ||
private Handler mRunnerThreadHandler; | ||
private int mCurrentTask; | ||
private Runnable[] mTasks; | ||
|
||
@Override | ||
public void onCreate() { | ||
Log.d(TAG, "Headless service created"); | ||
mRunnerThread = new HandlerThread("runnerThread"); | ||
mRunnerThread.start(); | ||
mRunnerThreadHandler = new Handler(mRunnerThread.getLooper()); | ||
|
||
mCurrentTask = 0; | ||
mTasks = new Runnable[] { | ||
new GPIOTask(), | ||
new LEDTask() | ||
}; | ||
|
||
Log.i(TAG, mTasks.length + " tasks available. Current task is " + | ||
getTaskName(mTasks[mCurrentTask])); | ||
Log.i(TAG, "Press the RM onboard button to select another task."); | ||
Log.i(TAG, "Press the PWR onboard button to execute the current task."); | ||
} | ||
|
||
private String getTaskName(Runnable r) { | ||
return r.getClass().getSimpleName(); | ||
} | ||
|
||
@Override | ||
public void onInputEvent(InputEvent event) { | ||
if (((KeyEvent) event).getAction() == KeyEvent.ACTION_DOWN) { | ||
switch (((KeyEvent) event).getScanCode()) { | ||
case BUTTON_EDISON_RM_KEYCODE: | ||
mCurrentTask = (mCurrentTask + 1) % mTasks.length; | ||
Log.d(TAG, "Button RM pressed. Changed current task to " + mCurrentTask + | ||
" (" + getTaskName(mTasks[mCurrentTask]) + "). Now press " + | ||
"PWR to execute it."); | ||
break; | ||
case BUTTON_EDISON_PWR_KEYCODE: | ||
Log.d(TAG, "Button PWR pressed. Executing task " + mCurrentTask + | ||
" (" + getTaskName(mTasks[mCurrentTask]) + ")"); | ||
executeCurrentTask(); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public void onDestroy() { | ||
if (mRunnerThread != null) { | ||
mRunnerThread.quit(); | ||
} | ||
} | ||
|
||
private void executeCurrentTask() { | ||
Log.d(TAG, "Executing task " + mCurrentTask + | ||
" (" + getTaskName(mTasks[mCurrentTask]) + ")"); | ||
Runnable r = mTasks[mCurrentTask]; | ||
|
||
// It is a good practice to execute I/O code in a separate thread | ||
mRunnerThreadHandler.post(r); | ||
} | ||
|
||
} |
102 changes: 102 additions & 0 deletions
102
app/src/main/java/com/google/samples/simplepio/task/GPIOTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
package com.google.samples.simplepio.task; | ||
|
||
import android.os.RemoteException; | ||
import android.pio.Gpio; | ||
import android.pio.PeripheralManagerService; | ||
import android.system.ErrnoException; | ||
import android.util.Log; | ||
|
||
import com.google.samples.simplepio.SimplePIOService; | ||
|
||
import java.util.List; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
/** | ||
* Simple GPIO port handling. | ||
*/ | ||
|
||
public class GPIOTask implements Runnable { | ||
private static final String TAG = SimplePIOService.TAG; | ||
|
||
private PeripheralManagerService mService; | ||
|
||
/** | ||
* Preferred GPIO port to look for. For example, on Intel Edison Arduino-compatible boards, | ||
* the port "IO13" has an onboard LED that turns on when the GPIO port is HIGH, and off | ||
* otherwise, so it is easy to debug that GPIO port' state without any extra hardware. | ||
*/ | ||
private static final String PREFERRED_GPIO_PORT = "IO13"; | ||
|
||
private static final int NUMBER_OF_BLINKS = 30; | ||
private static final int INTERVAL_BETWEEN_BLINKS_MS = 50; | ||
|
||
public GPIOTask() { | ||
mService = new PeripheralManagerService(); | ||
} | ||
|
||
@Override | ||
public void run() { | ||
Log.i(TAG, "Executing task GPIOTask"); | ||
try { | ||
List<String> gpios = listGpios(); | ||
if (gpios == null || gpios.isEmpty()) { | ||
return; | ||
} | ||
|
||
String portName; | ||
// if the preferred port exists, use it, otherwise use the first port identified. | ||
int preferred = gpios.indexOf(PREFERRED_GPIO_PORT); | ||
if (preferred >= 0) { | ||
portName = gpios.get(preferred); | ||
} else { | ||
portName = gpios.get(0); | ||
} | ||
|
||
// GPIO ports are single-user resources, so make sure you close them when you're done. | ||
// The "try with resources" syntax below is a good way of guaranteeing it. | ||
try (Gpio gpio = mService.openGpio(portName)) { | ||
gpio.setDirection(Gpio.DIRECTION_OUT_INITIALLY_LOW); | ||
blink(gpio, NUMBER_OF_BLINKS, INTERVAL_BETWEEN_BLINKS_MS); | ||
} | ||
// Notice that the gpio resource will be closed anyway, either if the | ||
// try(){} block finishes successfully or if an exception is thrown. | ||
// If you do not use a try(resource){} block, make sure you close the gpio port | ||
// in a finally clause, otherwise an ErrnoException will be thrown when | ||
// openGpio is called again on this port. | ||
|
||
} catch (RemoteException | ErrnoException e) { | ||
Log.e(TAG, "Error on PeripheralIO API", e); | ||
} | ||
} | ||
|
||
private List<String> listGpios() throws RemoteException { | ||
// List available GPIOs: | ||
List<String> gpios = mService.getGpioList(); | ||
if (gpios == null || gpios.isEmpty()) { | ||
Log.i(TAG, "No GPIO port available on this device."); | ||
} else { | ||
Log.i(TAG, "List of available GPIO ports: " + gpios); | ||
} | ||
return gpios; | ||
} | ||
|
||
private void blink(Gpio gpio, int numberOfBlinks, int intervalBetweenBlinksMs) | ||
throws RemoteException, ErrnoException { | ||
// Alternate GPIO output in a loop. Connect an LED to the port to see it blinking. | ||
for (int i=0; i < numberOfBlinks; i++) { | ||
|
||
// Turn on when i is even, off otherwise | ||
gpio.setValue( i % 2 == 0 ); | ||
|
||
// Sleep for a while | ||
try { | ||
TimeUnit.MILLISECONDS.sleep(intervalBetweenBlinksMs); | ||
} catch (InterruptedException e) { | ||
// Ignore sleep interruption. | ||
} | ||
} | ||
|
||
// Turn off at the end | ||
gpio.setValue(false); | ||
} | ||
} |
Oops, something went wrong.