In one of the projects, I needed to track the progress of native code execution on Android (specifically, ported FFmpeg). The situation was also complicated by the fact that for a number of reasons the code was executed in several processes.
Among the options considered were the following:
- IPC calls from sishnogo code
- logcat parsing
- data transfer through pipes
The most suitable option turned out to be the last one — using named pipes, the standard means for interprocess communication in unix-systems (for those unfamiliar with it, you can read it
here, for example). In short, it is a unidirectional FIFO channel with a file interface. When writing, it is blocked until another process opens it for reading and vice versa - while reading the channel is blocked again, until another process writes data to it. The big plus is that several processes can simultaneously write to the pipe.
Here lies a test project demonstrating the idea. It starts the service writing to the pipe from the native code, as well as the stream reader reading the result on the screen.
')
Stream-reader . Creates a new pipe with the mkfifo function (this is just a wrapper over the system call of the same name) and reads bytes from it, just like from a regular file. The read call blocks execution until someone on the other side of the pipe starts writing data. It uses a convenient class AsyncTask, which allows you to perform a function in the background and publish intermediate results in the UI-stream.
final TextView disp = new TextView( this );
disp.setText( "0" );
setContentView(disp);
final String pipename = getDir( "pipedemo" , Context.MODE_WORLD_WRITEABLE)
.getAbsolutePath() + "/pipe" ;
final File pipe = new File (pipename);
new AsyncTask<Void, Integer, Integer>() {
@Override
protected void onProgressUpdate(Integer... values) {
disp.setText( "" +values[0]);
};
protected Integer doInBackground(Void... params ) {
//create a pipe
if (mkfifo(pipename) == -1) {
Log.d(TAG, "Pipe error" );
return -1;
}
FileInputStream fis;
try {
fis = new FileInputStream(pipe);
int res = 0;
while (res != -1) { //blocks until someone writes to this pipe
res = fis.read();
publishProgress(res);
}
} catch (Exception e) {
e.printStackTrace();
}
return 0;
}
}.execute();
* This source code was highlighted with Source Code Highlighter .
Stream-writer . We launch it in a separate service. It performs a long-playing function, writing the progress of implementation in this very pipe.
final String pipename = intent.getStringExtra( "fn" );
new Thread( new Runnable() {
@Override
public void run() {
process(pipename);
}
}).start();
* This source code was highlighted with Source Code Highlighter .
Vorning 1 : Although the code can be executed in a separate process, run long operations in a separate thread, otherwise the system will kill the process without warning.
Vorning 2 : Do not create pipes on sdcard - FAT32 does not support them.
JNIEXPORT jint JNICALL Java_ru_jecklandin_cats_ProcessingService_process
(JNIEnv * env, jobject, jstring path) {
const char * cpath = env->GetStringUTFChars(path, NULL);
struct stat buf;
if ( stat(cpath, &buf) < 0 || ! (buf.st_mode | S_IFIFO)) {
LOGD( "The file isn't a pipe" );
return -1;
}
int fp = open(cpath, O_WRONLY);
if (fp == -1) {
LOGD( "Could not open the pipe" );
return -1;
}
for ( int i=0; i<10; ++i) {
sleep(1);
write(fp, &i, 1);
}
close(fp);
env->ReleaseStringUTFChars(path, cpath);
return 0;
}
* This source code was highlighted with Source Code Highlighter .
Add the attribute “process” to our service in the manifest.
< service android:name =".ProcessingService"
android:process =":remote" >
</ service >
* This source code was highlighted with Source Code Highlighter .
In DDMS, we see both processes.

Run and see the increasing tsiferku on the screen (not very impressive).
By the considered method it is possible to organize a duplex communication (having got one more pipe). Of course, the solution is not suitable for all cases. If you need to transfer objects, it is better to use the standard IPC-mechanism of Android, which allows you to transfer serialized objects between processes.
Literature:
developers.sun.com/solaris/articles/named_pipes.htmldeveloper.android.com/guide/developing/tools/aidl.html