Browse Source

jack2 supports android devices & rebase current changes to master

tags/v1.9.10
KimJeongYeon 10 years ago
parent
commit
4a94e12986
50 changed files with 6989 additions and 17 deletions
  1. +1241
    -0
      android/Android.mk
  2. +251
    -0
      android/AndroidShm.cpp
  3. +51
    -0
      android/AndroidShm.h
  4. +19
    -0
      android/AndroidShmServer/main_androidshmservice.cpp
  5. +23
    -0
      android/AndroidShmServer/readme.txt
  6. +177
    -0
      android/AndroidShmServer/test/shmservicedump.cpp
  7. +189
    -0
      android/AndroidShmServer/test/shmservicetest.cpp
  8. +83
    -0
      android/BnAndroidShm.cpp
  9. +16
    -0
      android/BnAndroidShm.h
  10. +111
    -0
      android/BpAndroidShm.cpp
  11. +25
    -0
      android/BpAndroidShm.h
  12. +66
    -0
      android/CleanSpec.mk
  13. +6
    -0
      android/IAndroidShm.cpp
  14. +41
    -0
      android/IAndroidShm.h
  15. +262
    -0
      android/JackAndroidSemaphore.cpp
  16. +76
    -0
      android/JackAndroidSemaphore.h
  17. +374
    -0
      android/JackAndroidThread.cpp
  18. +97
    -0
      android/JackAndroidThread.h
  19. +42
    -0
      android/JackAtomic_os.h
  20. +48
    -0
      android/JackCompilerDeps_os.h
  21. +89
    -0
      android/JackControlAPIAndroid.cpp
  22. +44
    -0
      android/JackControlAPIAndroid.h
  23. +153
    -0
      android/JackError.cpp
  24. +212
    -0
      android/JackGoldfishDriver.cpp
  25. +70
    -0
      android/JackGoldfishDriver.h
  26. +236
    -0
      android/JackOpenSLESDriver.cpp
  27. +70
    -0
      android/JackOpenSLESDriver.h
  28. +91
    -0
      android/JackPlatformPlug_os.h
  29. +40
    -0
      android/JackShmMem_os.h
  30. +32
    -0
      android/JackSystemDeps_os.h
  31. +869
    -0
      android/NOTICE
  32. +886
    -0
      android/Shm.cpp
  33. +144
    -0
      android/Shm.h
  34. +25
    -0
      android/config.h
  35. +14
    -0
      android/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include/bits/ctype_base.h
  36. +539
    -0
      android/opensl_io.c
  37. +121
    -0
      android/opensl_io.h
  38. +2
    -0
      common/JackConstants.h
  39. +34
    -0
      common/Jackdmp.cpp
  40. +2
    -2
      common/jack/types.h
  41. +21
    -1
      common/shm.h
  42. +9
    -0
      example-clients/alsa_in.c
  43. +9
    -0
      example-clients/alsa_out.c
  44. +1
    -1
      example-clients/midi_latency_test.c
  45. +20
    -0
      example-clients/transport.c
  46. +13
    -1
      linux/alsa/JackAlsaDriver.cpp
  47. +22
    -2
      linux/alsa/alsa_driver.c
  48. +18
    -8
      linux/alsa/alsa_rawmidi.c
  49. +3
    -2
      linux/alsa/alsa_seqmidi.c
  50. +2
    -0
      linux/alsa/hammerfall.c

+ 1241
- 0
android/Android.mk
File diff suppressed because it is too large
View File


+ 251
- 0
android/AndroidShm.cpp View File

@@ -0,0 +1,251 @@
#define LOG_TAG "JAMSHMSERVICE"

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <binder/MemoryHeapBase.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <utils/Log.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>
#include <sys/wait.h>
#include "BnAndroidShm.h"
#include "AndroidShm.h"


#include "JackConstants.h"


#include <fcntl.h>
#include <signal.h>
#include <limits.h>
#include <errno.h>
#include <dirent.h>
#include <sys/mman.h>
#include <linux/ashmem.h>
#include <cutils/ashmem.h>

#include "JackError.h"

#include <semaphore.h>


#define MEMORY_SIZE 10*1024

#define SEMAPHORE_NULL_CHAR '\0'

// remove ALOGI log
#undef ALOGI
#define ALOGI

namespace android {


int AndroidShm::instantiate() {
defaultServiceManager()->addService(String16("com.samsung.android.jam.IAndroidShm"), new AndroidShm); // SINGLETON WITH SAME NAME
return 0;
}

int AndroidShm::sendCommand(const char* command) {
ALOGI("I(pid:%d) send command is %s\n", getpid(), command);
if(strcmp(command, "semaphore") == 0) {
// print debug message about semaphore simulation
for(int i = MAX_SEMAPHORE_MEMORY_COUNT -1 ; i >= 0; i--) {
printf("index[%3d] = ptr[%p] name[%s]\n", i, (mSemaphore[i] != NULL)?mSemaphore[i]->getBase():0, mSemaphoreName[i]);
ALOGI("index[%3d] = ptr[%p] name[%s]\n", i, (mSemaphore[i] != NULL)?mSemaphore[i]->getBase():0, mSemaphoreName[i]);
}
}
return NO_ERROR;
}

int AndroidShm::testGetBufferByNewProcess() {
ALOGI("testGetBufferByNewProcess...");
int status;
int childPid = fork();
if(childPid > 0) {
ALOGI("I(pid%d) made a child process(pid:%d)", getpid(), childPid);
ALOGI("I(pid%d) wait until child(%d) was finish", getpid(), childPid);
wait(&status);
// wait ํ•˜์ง€ ์•Š์œผ๋ฉด child process๊ฐ€ ๋‚จ์•„ ์žˆ์Œ.
ALOGI("child(%d) was finished. ", childPid);
} else if(childPid == 0) {
ALOGI("im a new child process(pid:%d) ", getpid());
if(-1 == execlp("/system/bin/getbufferclient","getbufferclient",NULL)) {
ALOGE("failed to execute getbufferclient");
}
exit(0);
} else {
ALOGI("failed creating child process");
}
return 0;
}

int AndroidShm::testGetBuffer() {
ALOGI("I(pid:%d) trying to test get buffer...", getpid());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("get default ServiceManager is done");
sp<IBinder> b;
//String16* serviceName = new String16("com.samsung.android.jam.IAndroidShm");
do {
//ALOGI("here");
b = sm->getService(String16("com.samsung.android.jam.IAndroidShm"));
//ALOGI("getservice is done");
if(b != 0)
break;
//ALOGI("AndroidShm is not working, waiting...");
usleep(500000);
} while(true);
sp<IAndroidShm> service = interface_cast<IAndroidShm>(b);

//shared buffer.
sp<IMemoryHeap> receiverMemBase = service->getBuffer(0);
unsigned int *base = (unsigned int *) receiverMemBase->getBase();
int ret = 0;
if(base != (unsigned int *) -1) {
ALOGD("AndroidShm::testGetBuffer base=%p Data=0x%x\n",base, *base);
*base = (*base)+1;
ret = (unsigned int)(*base);
ALOGI("AndroidShm::testGetBuffer base=%p Data=0x%x CHANGED\n",base, *base);
receiverMemBase = 0;
} else {
ALOGE("Error shared memory not available\n");
}
return 0;
}

sp<IMemoryHeap> AndroidShm::getBuffer(int index) {
ALOGI("I(pid:%d) getBuffer index:%d", getpid(), index);
if(index < 0 || index >= MAX_SHARED_MEMORY_COUNT) {
ALOGE("error : out of index [%d]", index);
return NULL;
}
return mMemHeap[index];
}

int AndroidShm::MemAlloc(unsigned int size) {
ALOGI("try to allocate memory size[%d]", size);
for(int i = 0; i < MAX_SHARED_MEMORY_COUNT; i++) {
if(mMemHeap[i] == NULL) {
mMemHeap[i] = new MemoryHeapBase(size);
if(mMemHeap[i] == NULL){
ALOGI("fail to alloc, try one more...");
continue; // try one more.
}
return i;
}
}
ALOGE("fail to MemAlloc");
return -1; // fail to alloc
}

AndroidShm::AndroidShm() {
ALOGI("AndroidShm is created");
for(int i = 0; i < MAX_SHARED_MEMORY_COUNT; i++) {
mMemHeap[i] = NULL;
}
mRegistryIndex = 10000;
//mMemHeap = new MemoryHeapBase(MEMORY_SIZE);
//unsigned int *base = (unsigned int*) mMemHeap->getBase();
//*base = 0xdeadcafe;//

for(int j = 0; j < MAX_SEMAPHORE_MEMORY_COUNT; j++) {
mSemaphore[j] = NULL;
memset(mSemaphoreName[j], SEMAPHORE_NULL_CHAR, MAX_SEMAPHORE_NAME_LENGTH);
}
}

AndroidShm::~AndroidShm() {
ALOGI("AndroidShm is destroyed");
for(int i = 0; i < MAX_SHARED_MEMORY_COUNT; i++) {
(mMemHeap[i]).clear();
}
for(int j = 0; j < MAX_SEMAPHORE_MEMORY_COUNT; j++) {
(mSemaphore[j]).clear();
}
}

//status_t AndroidShm::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
// return BnAndroidShm::onTransact(code, data, reply, flags);
//}

int AndroidShm::allocShm(const int size) { // if negative return value is error
ALOGI("try to alloc shared memory size[%d]", size);
return MemAlloc(size);
}
int AndroidShm::removeShm(const unsigned int index) { // shared memory ์ œ๊ฑฐ
ALOGI("try to remove shared memory index[%d]", index);
if(index >= MAX_SHARED_MEMORY_COUNT) {
ALOGE("remove shared memory: out of index");
return -1;
}
(mMemHeap[index]).clear();
return 1;
}

int AndroidShm::isAllocated(const unsigned int index) { // allocated ์—ฌ๋ถ€ ํ™•์ธ
ALOGI("try to check the memory allocation index[%d]", index);
if(index >= MAX_SHARED_MEMORY_COUNT) {
ALOGE("shared memory: out of index");
return 0;
}
if(mMemHeap[index] == NULL)
return 0;
else
return 1;
}

int AndroidShm::setRegistryIndex(const unsigned int index) {
ALOGI("set registry index %d", index);
mRegistryIndex = index;
return 1;
}
int AndroidShm::getRegistryIndex() {
return mRegistryIndex;
}

sp<IMemoryHeap> AndroidShm::InitSemaphore(const char* name) {
ALOGI("init semaphore [%s]", name);
for(int i = 0; i < MAX_SEMAPHORE_MEMORY_COUNT; i++) {
if(mSemaphoreName[i][0] == SEMAPHORE_NULL_CHAR) {
mSemaphore[i] = new MemoryHeapBase(sizeof(sem_t));
if(mSemaphore[i] == NULL){
ALOGI("fail to alloc, try one more...");
continue;
}
if(sem_init((sem_t*)(mSemaphore[i]->getBase()), 1, 0) == 0) {
strncpy(mSemaphoreName[i], name, MAX_SEMAPHORE_NAME_LENGTH - 1);
mSemaphoreName[i][MAX_SEMAPHORE_NAME_LENGTH - 1] = '\0';
ALOGI("sem_init success");
return mSemaphore[i];
} else {
(mSemaphore[i]).clear();
ALOGE("sem_init failed null returned");
return NULL;
}
} else {
// find already exist name
if(strcmp(mSemaphoreName[i], name) == 0) { // found
ALOGI("found - return alread allocated semaphore");
return mSemaphore[i];
}
}
}
ALOGE("sem_init failed null returned 2");
return NULL;
}

};


+ 51
- 0
android/AndroidShm.h View File

@@ -0,0 +1,51 @@
#ifndef ANDROIDSHM
#define ANDROIDSHM

#include <binder/Parcel.h>
#include "BnAndroidShm.h"
#include <utils/Log.h>
#include <binder/MemoryHeapBase.h>
#include "shm.h"
#include "android/Shm.h" //android extension of shm.h

namespace android {

class AndroidShm : public BnAndroidShm
{
#define MAX_SHARED_MEMORY_COUNT 257
private:
int MemAlloc(unsigned int size);
public:
virtual ~AndroidShm();
static int instantiate();
virtual int sendCommand(const char* command);
virtual int allocShm(const int size); // if negative return value is error
virtual int removeShm(const unsigned int index); // shared memory รยฆยฐร…
virtual int isAllocated(const unsigned int index); // allocated ยฟยฉยบรŽ รˆยฎร€รŽ
virtual int setRegistryIndex(const unsigned int index);
virtual int getRegistryIndex();
virtual sp<IMemoryHeap> InitSemaphore(const char* name);
virtual sp<IMemoryHeap> getBuffer(int index);
//virtual status_t onTransact(
// uint32_t code,
// const Parcel& data,
// Parcel* reply,
// uint32_t flags);
private:
int testGetBuffer();
int testGetBufferByNewProcess();
AndroidShm();

sp<MemoryHeapBase> mMemHeap[MAX_SHARED_MEMORY_COUNT];
unsigned int mRegistryIndex;

// for named semaphore simulation
#define MAX_SEMAPHORE_MEMORY_COUNT 300
#define MAX_SEMAPHORE_NAME_LENGTH 300
sp<MemoryHeapBase> mSemaphore[MAX_SEMAPHORE_MEMORY_COUNT];
char mSemaphoreName[MAX_SEMAPHORE_MEMORY_COUNT][MAX_SEMAPHORE_NAME_LENGTH];
};
};

#endif

+ 19
- 0
android/AndroidShmServer/main_androidshmservice.cpp View File

@@ -0,0 +1,19 @@
#define LOG_TAG "main_androidshmservice"

#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>

#include "../../common/shm.h"
#include "../Shm.h" //android extension of shm.h

using namespace android;

int main(int argc, char *argv[]) {
jack_instantiate();
ProcessState::self()->startThreadPool();
ALOGI("AndroidShmService is starting now");
IPCThreadState::self()->joinThreadPool();
return 0;
}

+ 23
- 0
android/AndroidShmServer/readme.txt View File

@@ -0,0 +1,23 @@
IAndroidShm์˜ ๊ธฐ๋Šฅ์„ ํ…Œ์ŠคํŠธ ํ•˜๊ธฐ ์œ„ํ•œ ์šฉ๋„๋กœ ์‚ฌ์šฉ๋˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค.

AndroidShm์€ service manager์— shared memory๋ฅผ ํ• ๋‹นํ•ด์ฃผ๋Š” ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค.

service name: com.sec.apa.IAndroidShm

์‹คํ–‰ ํŒŒ์ผ:
/system/bin/androidshmservice

-------------------------------------------
./test

AndroidShmService๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ

/system/bin/shmservicetest

AndroidShmService์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์„ UnitTestํ•ฉ๋‹ˆ๋‹ค.

๋™์ž‘ ํ™•์ธ ๋ฐฉ๋ฒ•:
adb logcat ์œผ๋กœ ๋กœ๊ทธ๋กœ ์„ฑ๊ณต/์‹คํŒจ ํ™•์ธํ•จ.

์ „์ œ ์กฐ๊ฑด:
/system/bin/androidshmservice๋ฅผ ์‹คํ–‰์ค‘์ธ ์ƒํƒœ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

+ 177
- 0
android/AndroidShmServer/test/shmservicedump.cpp View File

@@ -0,0 +1,177 @@
#include "../../IAndroidShm.h"
#include <binder/MemoryHeapBase.h>
#include <binder/IServiceManager.h>
#include "../../../common/shm.h"

namespace android {

static sp<IMemoryHeap> receiverMemBase;
#define MAX_SHARED_MEMORY_COUNT 257

sp<IAndroidShm> getAndroidShmService() {
sp<IAndroidShm> shm = 0;

/* Get the buffer service */
if (shm == NULL) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
binder = sm->getService(String16("com.samsung.android.jam.IAndroidShm"));
if (binder != 0) {
shm = IAndroidShm::asInterface(binder);
//shm = interface_cast<IAndroidShm>(binder);
}
}
return shm;
}

unsigned int * getBufferMemPointer(int index)
{
sp<IAndroidShm> shm = getAndroidShmService();
if (shm == NULL) {
printf("The EneaBufferServer is not published\n");
return (unsigned int *)-1; /* return an errorcode... */
} else {
receiverMemBase = shm->getBuffer(index);
if(receiverMemBase != NULL)
return (unsigned int *) receiverMemBase->getBase();
else
return (unsigned int*)-1;
}
}

}

using namespace android;

void showStatus() {
sp<IAndroidShm> shm = getAndroidShmService();
if(shm == NULL) {
printf("shm service is not available\n");
return;
}
printf("<<<<<<<<<<< dump memory allocation status >>>>>>>>>>\n");
for(int i = 256; i >= 0; i--) {
if(shm->isAllocated(i) == 1) {
printf("Mem[%3d] == 0x%x\n", i, (unsigned int)getBufferMemPointer(i));
} else {
printf("Mem[%3d] == NULL\n", i);
}
}
}

void showRegistryIndex() {
sp<IAndroidShm> shm = getAndroidShmService();

if(shm == NULL) {
printf("shm service is not available\n");
return;
}

printf("<<<<<<<<<<< show registry index >>>>>>>>>>\n");

printf("index [%3d]\n",shm->getRegistryIndex());
}

void showHeader() {
sp<IAndroidShm> shm = getAndroidShmService();

if(shm == NULL) {
printf("shm service is not available\n");
return;
}

if(shm->getRegistryIndex() > 256) {
printf("don't have a registry header\n");
return;
}
unsigned int* buffer = getBufferMemPointer(shm->getRegistryIndex());
if(buffer) {
jack_shm_header_t * header = (jack_shm_header_t*)buffer;
printf("<<<<<<<<<< register header value >>>>>>>>>>\n");
printf("memory address 0x%x 0x%x\n", (unsigned int)(header), (unsigned int)buffer);
printf("magic = %d\n", header->magic);
printf("protocol = %d\n", header->protocol);
printf("type = %d\n", header->type);
printf("size = %d\n", header->size);
printf("hdr_len = %d\n", header->hdr_len);
printf("entry_len = %d\n", header->entry_len);
for(int j = 0; j < MAX_SERVERS; j++) {
//char name[256];
//memset(name, '\0', 256);
//strncpy(name, header->server[j].name, 10);
printf("server[%d] pid = %d, name = %s\n", j, header->server[j].pid, header->server[j].name);
}
}
}

void showBody() {
sp<IAndroidShm> shm = getAndroidShmService();

if(shm == NULL) {
printf("shm service is not available\n");
return;
}
if(shm->getRegistryIndex() > 256) {
printf("don't have a registry body\n");
return;
}
unsigned int* buffer = getBufferMemPointer(shm->getRegistryIndex());
if(buffer) {
jack_shm_header_t * header = (jack_shm_header_t*)buffer;
printf("<<<<<<<<<< registry body value >>>>>>>>>>\n");
jack_shm_registry_t * registry = (jack_shm_registry_t *) (header + 1);
for(int k = 255; k >= 0; k--) {
printf("registry[%3d] index[%3d],allocator[%3d],size[%6d],id[%10s],fd[%3d]\n", k,
registry[k].index, registry[k].allocator, registry[k].size,
registry[k].id,
registry[k].fd);
}
}
}

void showSemaphore() {
sp<IAndroidShm> shm = getAndroidShmService();

if(shm == NULL) {
printf("shm service is not available\n");
return;
}

shm->sendCommand("semaphore");
printf("log will be shown in the logcat log\n");
}

int main(int argc, char** argv) {
// base could be on same address as Servers base but this
// is purely by luck do NEVER rely on this. Linux memory
// management may put it wherever it likes.

if(argc < 2) {
printf("usage\n shmservicedump [status|header|body|index|semaphore]\n");
printf(" status: show the shared memory allocation status\n");
printf(" header: show the registry header infomations if the registry exist\n");
printf(" body: show the registry body infomations if the registry exist\n");
printf(" index: show the index of array that is allocated registry shared memory\n");
printf(" semaphore: show the memory array about semaphore simulation\n");
return 0;
}

if(strcmp(argv[1], "semaphore") == 0) {
showSemaphore();
} else if(strcmp(argv[1], "index") == 0) {
showRegistryIndex();
} else if(strcmp(argv[1], "status") == 0) {
showStatus();
} else if(strcmp(argv[1], "header") == 0) {
showHeader();
} else if(strcmp(argv[1], "body") == 0) {
showBody();
} else {
printf("%s is invalid parameter\n", argv[1]);
}
return 0;
}

+ 189
- 0
android/AndroidShmServer/test/shmservicetest.cpp View File

@@ -0,0 +1,189 @@
#include "../../IAndroidShm.h"
#include <binder/MemoryHeapBase.h>
#include <binder/IServiceManager.h>

namespace android {

static sp<IMemoryHeap> receiverMemBase;
#define MAX_SHARED_MEMORY_COUNT 257

sp<IAndroidShm> getAndroidShmService() {
sp<IAndroidShm> shm = 0;

/* Get the buffer service */
if (shm == NULL) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder;
binder = sm->getService(String16("com.samsung.android.jam.IAndroidShm"));
if (binder != 0) {
shm = IAndroidShm::asInterface(binder);
//shm = interface_cast<IAndroidShm>(binder);
}
}
return shm;
}

unsigned int * getBufferMemPointer(int index) {
sp<IAndroidShm> shm = getAndroidShmService();
if (shm == NULL) {
ALOGE("The EneaBufferServer is not published");
return (unsigned int *)-1; /* return an errorcode... */
} else {
receiverMemBase = shm->getBuffer(index);
if(receiverMemBase != NULL)
return (unsigned int *) receiverMemBase->getBase();
else
return (unsigned int*)-1;
}
}

}

using namespace android;

void setup_test() {
sp<IAndroidShm> shm = getAndroidShmService();
if(shm == NULL) return;
for(int i = 0; i < MAX_SHARED_MEMORY_COUNT; i++) {
shm->removeShm(i);
}
}

void teardown_test() {
}

void increase_value_once() {
ALOGD("*****test: increase_value_once*****\n");
sp<IAndroidShm> shm = getAndroidShmService();
if(shm == NULL) return;

int slot = shm->allocShm(10000);
unsigned int *base = getBufferMemPointer(slot);
if(base != (unsigned int *)-1) {
ALOGD("ShmServiceTest base=%p Data=0x%x\n",base, *base);
*base = (*base)+1;
ALOGD("ShmServiceTest base=%p Data=0x%x CHANGED\n",base, *base);
//receiverMemBase = 0;
} else {
ALOGE("Error shared memory not available\n");
}
}

void increase_value_10times() {
ALOGD("*****test: increase_value_10times*****\n");
sp<IAndroidShm> shm = getAndroidShmService();
if(shm == NULL) return;

int slot = shm->allocShm(10000);

for(int i = 0; i < 10; i++) {
unsigned int *base = getBufferMemPointer(slot);
if(base != (unsigned int *)-1) {
ALOGD("ShmServiceTest base=%p Data=0x%x\n",base, *base);
*base = (*base)+1;
ALOGD("ShmServiceTest base=%p Data=0x%x CHANGED\n",base, *base);
//receiverMemBase = 0;
} else {
ALOGE("Error shared memory not available\n");
}
}
}

void check_allocated() {
ALOGD("*****test: check_allocated*****\n");
sp<IAndroidShm> shm = getAndroidShmService();
if(shm == NULL) return;

int slot = shm->allocShm(10000);
int i = 0;
for(; i < MAX_SHARED_MEMORY_COUNT; i++) {
if(slot == i) {
if(shm->isAllocated(i) == 1) {
//ALOGD("pass\n");
} else {
ALOGD("failed\n");
}
} else {
if(shm->isAllocated(i) == 0) {
//ALOGD("pass\n");
} else {
ALOGD("failed\n");
}
}
}

if(i == MAX_SHARED_MEMORY_COUNT) {
ALOGD("pass\n");
}
}

void test_set_get_registry_index() {
ALOGD("*****test: test_set_get_registry_index*****\n");
sp<IAndroidShm> shm = getAndroidShmService();
if(shm == NULL) return;

int registry = 1;
shm->setRegistryIndex(registry);
if(registry == shm->getRegistryIndex()) {
ALOGD("pass\n");
} else {
ALOGD("fail\n");
}

registry = 0;
shm->setRegistryIndex(registry);
if(registry == shm->getRegistryIndex()) {
ALOGD("pass\n");
} else {
ALOGD("fail\n");
}
}

void test_memset() {
ALOGD("*****test: test_memset*****\n");
sp<IAndroidShm> shm = getAndroidShmService();
if(shm == NULL) return;

int slot = shm->allocShm(10000);

unsigned int * pnt = getBufferMemPointer(slot);

memset (pnt, 0, 10000);

ALOGD("result : 0 0 0 0\n");
ALOGD("memory dump : %d %d %d %d\n", pnt[0], pnt[1], pnt[2], pnt[3]);
memset (pnt, 0xffffffff, 10000);

ALOGD("result : -1 -1 -1 -1\n");
ALOGD("memory dump : %d %d %d %d", pnt[0], pnt[1], pnt[2], pnt[3]);
}

int main(int argc, char** argv) {
// base could be on same address as Servers base but this
// is purely by luck do NEVER rely on this. Linux memory
// management may put it wherever it likes.

setup_test();
increase_value_once();
teardown_test();

setup_test();
increase_value_10times();
teardown_test();

setup_test();
check_allocated();
teardown_test();

setup_test();
test_set_get_registry_index();
teardown_test();

setup_test();
test_memset();
teardown_test();

return 0;
}


+ 83
- 0
android/BnAndroidShm.cpp View File

@@ -0,0 +1,83 @@
#include "BnAndroidShm.h"
#include <binder/Parcel.h>

namespace android {
status_t BnAndroidShm::onTransact( uint32_t code,
const Parcel &data,
Parcel *reply,
uint32_t flags)
{
switch(code) {
case HW_SENDCOMMAND:{
CHECK_INTERFACE(IAndroidShm, data, reply);
const char *str;
str = data.readCString();
reply->writeInt32(sendCommand(str));
return NO_ERROR;
}break;

case HW_GETBUFFER:{
CHECK_INTERFACE(IAndroidShm, data, reply);
int32_t index;
data.readInt32(&index);
sp<IMemoryHeap> Data = getBuffer(index);
if(Data != NULL){
reply->writeStrongBinder(Data->asBinder());
}
return NO_ERROR;
}break;

case HW_ALLOC_SHM:{
CHECK_INTERFACE(IAndroidShm, data, reply);
int32_t size;
data.readInt32(&size);
reply->writeInt32(allocShm(size));
return NO_ERROR;
}break;

case HW_REMOVE_SHM:{
CHECK_INTERFACE(IAndroidShm, data, reply);
int32_t index;
data.readInt32(&index);
reply->writeInt32(removeShm(index));
return NO_ERROR;
}break;
case HW_IS_ALLOCATED:{
CHECK_INTERFACE(IAndroidShm, data, reply);
int32_t index;
data.readInt32(&index);
reply->writeInt32(isAllocated(index));
return NO_ERROR;
}break;

case HW_SET_REGISTRY_INDEX:{
CHECK_INTERFACE(IAndroidShm, data, reply);
int32_t index;
data.readInt32(&index);
reply->writeInt32(setRegistryIndex(index));
return NO_ERROR;
}break;

case HW_GET_REGISTRY_INDEX:{
CHECK_INTERFACE(IAndroidShm, data, reply);
reply->writeInt32(getRegistryIndex());
return NO_ERROR;
}break;

case HW_INIT_SEMAPHORE:{
CHECK_INTERFACE(IAndroidShm, data, reply);
const char *name;
name = data.readCString();
sp<IMemoryHeap> Data = InitSemaphore(name);
if(Data != NULL){
reply->writeStrongBinder(Data->asBinder());
}
return NO_ERROR;
}break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
};

+ 16
- 0
android/BnAndroidShm.h View File

@@ -0,0 +1,16 @@
#ifndef BNANDROIDSHM
#define BNANDROIDSHM

#include <binder/Parcel.h>
#include "IAndroidShm.h"

namespace android {
class BnAndroidShm : public BnInterface<IAndroidShm> {
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
};
#endif

+ 111
- 0
android/BpAndroidShm.cpp View File

@@ -0,0 +1,111 @@
#include <binder/Parcel.h>
#include <utils/Log.h>
#include "BpAndroidShm.h"

namespace android{

int BpAndroidShm::sendCommand(const char*command) {
Parcel data, reply;
data.writeInterfaceToken(
IAndroidShm::getInterfaceDescriptor());
data.writeCString(command);
status_t status = remote()->transact(HW_SENDCOMMAND, data, &reply);
if(status != NO_ERROR) {
ALOGE("print sendCommand error: %s", strerror(-status));
} else {
status= reply.readInt32();
}
return status;
}

sp<IMemoryHeap> BpAndroidShm::getBuffer(int index) {
Parcel data, reply;
sp<IMemoryHeap> memHeap = NULL;
data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor());
data.writeInt32(index);
remote()->transact(HW_GETBUFFER, data, &reply);
memHeap = interface_cast<IMemoryHeap> (reply.readStrongBinder());
return memHeap;
}

BpAndroidShm::BpAndroidShm( const sp<IBinder>& impl)
: BpInterface<IAndroidShm>(impl)
{}

BpAndroidShm::~BpAndroidShm()
{}

int BpAndroidShm::allocShm(const int size) { // if negative return value is error
Parcel data, reply;
data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor());
data.writeInt32(size);
status_t status = remote()->transact(HW_ALLOC_SHM, data, &reply);
if(status != NO_ERROR) {
ALOGE("print allocShm error: %s", strerror(-status));
} else {
status= reply.readInt32();
}
return status;
}
int BpAndroidShm::removeShm(const unsigned int index) { // shared memory รยฆยฐร…
Parcel data, reply;
data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor());
data.writeInt32(index);
status_t status = remote()->transact(HW_REMOVE_SHM, data, &reply);
if(status != NO_ERROR) {
ALOGE("print removeShm error: %s", strerror(-status));
} else {
status= reply.readInt32();
}
return status;
}

int BpAndroidShm::isAllocated(const unsigned int index) { // allocated ยฟยฉยบรŽ รˆยฎร€รŽ
Parcel data, reply;
data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor());
data.writeInt32(index);
status_t status = remote()->transact(HW_IS_ALLOCATED, data, &reply);
if(status != NO_ERROR) {
ALOGE("print isAllocated error: %s", strerror(-status));
} else {
status= reply.readInt32();
}
return status;
}

int BpAndroidShm::setRegistryIndex(const unsigned int index) {
Parcel data, reply;
data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor());
data.writeInt32(index);
status_t status = remote()->transact(HW_SET_REGISTRY_INDEX, data, &reply);
if(status != NO_ERROR) {
ALOGE("print setRegistryIndex error: %s", strerror(-status));
} else {
status= reply.readInt32();
}
return status;
}

int BpAndroidShm::getRegistryIndex() {
Parcel data, reply;
data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor());
status_t status = remote()->transact(HW_GET_REGISTRY_INDEX, data, &reply);
if(status != NO_ERROR) {
ALOGE("print getRegistryIndex error: %s", strerror(-status));
} else {
status= reply.readInt32();
}
return status;
}

sp<IMemoryHeap> BpAndroidShm::InitSemaphore(const char* name) {
Parcel data, reply;
sp<IMemoryHeap> memHeap = NULL;
data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor());
data.writeCString(name);
status_t status = remote()->transact(HW_INIT_SEMAPHORE, data, &reply);
memHeap = interface_cast<IMemoryHeap> (reply.readStrongBinder());
return memHeap;
}
};

+ 25
- 0
android/BpAndroidShm.h View File

@@ -0,0 +1,25 @@
#ifndef BPANDROIDSHM
#define BPANDROIDSHM

#include <binder/Parcel.h>
#include "IAndroidShm.h"
#include <binder/IMemory.h>

namespace android {
class BpAndroidShm: public BpInterface<IAndroidShm> {
public:
BpAndroidShm( const sp<IBinder> & impl);
virtual ~BpAndroidShm();
virtual sp<IMemoryHeap> getBuffer(int index);
virtual int sendCommand(const char *command);
virtual int allocShm(const int size); // if negative return value is error
virtual int removeShm(const unsigned int index); // shared memory รยฆยฐร…
virtual int isAllocated(const unsigned int index); // allocated ยฟยฉยบรŽ รˆยฎร€รŽ
virtual int setRegistryIndex(const unsigned int index);
virtual int getRegistryIndex();

virtual sp<IMemoryHeap> InitSemaphore(const char* name);
};
};

#endif

+ 66
- 0
android/CleanSpec.mk View File

@@ -0,0 +1,66 @@

$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/common)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/alsa_in_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/alsa_out_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/androidshmservice_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/shmservicetest_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/shmservicedump_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_samplerate_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_freewheel_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_connect_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_disconnect_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_latent_client_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_midiseq_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_zombie_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_lsp_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_load_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jackd_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_monitor_client_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_simple_looper_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_simple_client_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_cpu_load_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_iodelay_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_midisine_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_cpu_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_simple_keyboard_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_unload_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_wait_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_alias_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_metro_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_bufsize_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_thru_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_session_notify_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_midi_latency_test_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_rec_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_netsource_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_net_master_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_net_slave_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_showtime_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_server_control_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_evmon_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_test_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_transport_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_simple_session_client_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_simple_effect_intermediates)
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_multiple_metro_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_midi_dump_intermediates)

$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/common)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/posix)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjack_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjacknet_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjackserver_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjackshm_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_alsa_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_dummy_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_net_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_loopback_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_netone_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/audioadapter_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/example_lib_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/netadapter_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/netmanager_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/profiler_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_goldfish_intermediates)
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_opensles_intermediates)


+ 6
- 0
android/IAndroidShm.cpp View File

@@ -0,0 +1,6 @@
#include "IAndroidShm.h"
#include "BpAndroidShm.h"

namespace android{
IMPLEMENT_META_INTERFACE(AndroidShm, "com.samsung.android.jam.IAndroidShm");
};

+ 41
- 0
android/IAndroidShm.h View File

@@ -0,0 +1,41 @@
#ifndef IANDROIDSHM
#define IANDROIDSHM

#include <binder/IInterface.h>
#include <binder/IMemory.h>

namespace android {

enum {
HW_GETBUFFER = IBinder::FIRST_CALL_TRANSACTION,
HW_MULTIPLY,
HW_STARTSERVER,
HW_MAKECLIENT,
HW_SENDCOMMAND,
HW_LOADSO,
HW_ALLOC_SHM,
HW_REMOVE_SHM,
HW_IS_ALLOCATED,
HW_SET_REGISTRY_INDEX,
HW_GET_REGISTRY_INDEX,
HW_INIT_SEMAPHORE
};
class IAndroidShm: public IInterface {
public:
DECLARE_META_INTERFACE(AndroidShm);

virtual sp<IMemoryHeap> getBuffer(int index) = 0;
virtual int sendCommand(const char *command) = 0;
virtual int allocShm(const int size) = 0; // if negative return value is error
virtual int removeShm(const unsigned int index) = 0; // shared memory รยฆยฐร…
virtual int isAllocated(const unsigned int index) = 0; // allocated ยฟยฉยบรŽ รˆยฎร€รŽ
virtual int setRegistryIndex(const unsigned int index) = 0;
virtual int getRegistryIndex() = 0;

// for named semaphore simulation
virtual sp<IMemoryHeap> InitSemaphore(const char* name) = 0;
};
};

#endif

+ 262
- 0
android/JackAndroidSemaphore.cpp View File

@@ -0,0 +1,262 @@
/*
Copyright (C) 2004-2008 Grame
Copyright (C) 2013 Samsung Electronics

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*/

#include "JackAndroidSemaphore.h"
#include "JackTools.h"
#include "JackConstants.h"
#include "JackError.h"
#include <fcntl.h>
#include <stdio.h>
#include <sys/time.h>
#include "IAndroidShm.h"
#include "shm.h"
#include "android/Shm.h" //android extension of shm.h

namespace Jack
{

pthread_mutex_t JackAndroidSemaphore::mutex = PTHREAD_MUTEX_INITIALIZER;

void JackAndroidSemaphore::BuildName(const char* client_name, const char* server_name, char* res, int size)
{
char ext_client_name[SYNC_MAX_NAME_SIZE + 1];
JackTools::RewriteName(client_name, ext_client_name);
if (getenv("JACK_PROMISCUOUS_SERVER")) {
snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name);
} else {
snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name);
}
}

bool JackAndroidSemaphore::Signal()
{
int res;

if (!fSemaphore) {
jack_error("JackAndroidSemaphore::Signal name = %s already deallocated!!", fName);
return false;
}

if (fFlush)
return true;

if ((res = sem_post(fSemaphore)) != 0) {
jack_error("JackAndroidSemaphore::Signal name = %s err = %s", fName, strerror(errno));
}
return (res == 0);
}

bool JackAndroidSemaphore::SignalAll()
{
int res;

if (!fSemaphore) {
jack_error("JackAndroidSemaphore::SignalAll name = %s already deallocated!!", fName);
return false;
}

if (fFlush)
return true;

if ((res = sem_post(fSemaphore)) != 0) {
jack_error("JackAndroidSemaphore::SignalAll name = %s err = %s", fName, strerror(errno));
}
return (res == 0);
}

/*
bool JackAndroidSemaphore::Wait()
{
int res;

if (!fSemaphore) {
jack_error("JackAndroidSemaphore::Wait name = %s already deallocated!!", fName);
return false;
}

if ((res = sem_wait(fSemaphore)) != 0) {
jack_error("JackAndroidSemaphore::Wait name = %s err = %s", fName, strerror(errno));
}
return (res == 0);
}
*/

bool JackAndroidSemaphore::Wait()
{
int res;

while ((res = sem_wait(fSemaphore) < 0)) {
jack_error("JackAndroidSemaphore::Wait name = %s err = %s", fName, strerror(errno));
if (errno != EINTR) {
break;
}
}
return (res == 0);
}

bool JackAndroidSemaphore::TimedWait(long usec)
{
int res;
struct timeval now;
timespec time;

if (!fSemaphore) {
jack_error("JackAndroidSemaphore::TimedWait name = %s already deallocated!!", fName);
return false;
}
gettimeofday(&now, 0);
time.tv_sec = now.tv_sec + usec / 1000000;
long tv_usec = (now.tv_usec + (usec % 1000000));
time.tv_sec += tv_usec / 1000000;
time.tv_nsec = (tv_usec % 1000000) * 1000;

while ((res = sem_timedwait(fSemaphore, &time)) < 0) {
jack_error("JackAndroidSemaphore::TimedWait err = %s", strerror(errno));
jack_log("JackAndroidSemaphore::TimedWait now : %ld %ld ", now.tv_sec, now.tv_usec);
jack_log("JackAndroidSemaphore::TimedWait next : %ld %ld ", time.tv_sec, time.tv_nsec/1000);
if (errno == ETIMEDOUT) {
timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec = time.tv_sec - ts.tv_sec;
ts.tv_nsec = time.tv_nsec - ts.tv_nsec;
if (ts.tv_nsec < 0) {
ts.tv_nsec += 1000000000;
ts.tv_sec -= 1;
}
if (ts.tv_sec < 0 || ts.tv_nsec < 0) {
jack_error("JackAndroidSemaphore::TimedWait time may changed or client killed already! wait again!");
gettimeofday(&now, 0);
time.tv_sec = now.tv_sec + usec / 1000000;
long tv_usec = (now.tv_usec + (usec % 1000000));
time.tv_sec += tv_usec / 1000000;
time.tv_nsec = (tv_usec % 1000000) * 1000;
if ((res = sem_timedwait(fSemaphore, &time)) < 0) {
jack_error("JackAndroidSemaphore::TimedWait err = %s", strerror(errno));
jack_log("JackAndroidSemaphore::TimedWait now : %ld %ld ", now.tv_sec, now.tv_usec);
jack_log("JackAndroidSemaphore::TimedWait next : %ld %ld ", time.tv_sec, time.tv_nsec/1000);
}
}
}
if (errno != EINTR) {
break;
}
}
return (res == 0);
}

// Server side : publish the semaphore in the global namespace
bool JackAndroidSemaphore::Allocate(const char* name, const char* server_name, int value)
{
pthread_mutex_lock (&mutex);
BuildName(name, server_name, fName, sizeof(fName));
jack_log("JackAndroidSemaphore::Allocate name = %s val = %ld", fName, value);

android::sp<android::IAndroidShm> service = android::Shm::getShmService();
if(service == NULL){
jack_error("shm service is null");
return false;
}
fSemaphoreMemory = service->InitSemaphore(fName);
if(fSemaphoreMemory != NULL){
fSemaphore = (sem_t*)(fSemaphoreMemory->getBase());
}

if(fSemaphore == NULL) {
jack_error("Allocate: can't check in named semaphore name = %s err = %s", fName, strerror(errno));
pthread_mutex_unlock (&mutex);
return false;
} else {
sem_init(fSemaphore, 1, 0);
jack_log("sem_init()");
pthread_mutex_unlock (&mutex);
return true;
}
}

// Client side : get the published semaphore from server
bool JackAndroidSemaphore::ConnectInput(const char* name, const char* server_name)
{
pthread_mutex_lock (&mutex);
BuildName(name, server_name, fName, sizeof(fName));
jack_log("JackAndroidSemaphore::Connect name = %s", fName);

// Temporary...
if (fSemaphore) {
jack_log("Already connected name = %s", name);
pthread_mutex_unlock (&mutex);
return true;
}

android::sp<android::IAndroidShm> service = android::Shm::getShmService();
if(service == NULL){
jack_error("shm service is null");
return false;
}

fSemaphoreMemory = service->InitSemaphore(fName);
if(fSemaphoreMemory != NULL){
fSemaphore = (sem_t*)(fSemaphoreMemory->getBase());
}

if(fSemaphore == NULL) {
jack_error("Connect: can't connect named semaphore name = %s err = %s", fName, strerror(errno));
pthread_mutex_unlock (&mutex);
return false;
} else {
int val = 0;
sem_getvalue(fSemaphore, &val);
jack_log("JackAndroidSemaphore::Connect sem_getvalue %ld", val);
pthread_mutex_unlock (&mutex);
return true;
}
}

bool JackAndroidSemaphore::Connect(const char* name, const char* server_name)
{
return ConnectInput(name, server_name);
}

bool JackAndroidSemaphore::ConnectOutput(const char* name, const char* server_name)
{
return ConnectInput(name, server_name);
}

bool JackAndroidSemaphore::Disconnect()
{
if (fSemaphore) {
jack_log("JackAndroidSemaphore::Disconnect name = %s", fName);
fSemaphore = NULL;
}
return true;
}

// Server side : destroy the semaphore
void JackAndroidSemaphore::Destroy()
{
if (fSemaphore != NULL) {
jack_log("JackAndroidSemaphore::Disconnect name = %s", fName);
fSemaphore = NULL;
} else {
jack_error("JackAndroidSemaphore::Destroy semaphore == NULL");
}
}

} // end of namespace


+ 76
- 0
android/JackAndroidSemaphore.h View File

@@ -0,0 +1,76 @@
/*
Copyright (C) 2004-2008 Grame
Copyright (C) 2013 Samsung Electronics

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*/

#ifndef __JackAndroidSemaphore__
#define __JackAndroidSemaphore__

#include "JackSynchro.h"
#include "JackCompilerDeps.h"
#include <semaphore.h>
#include <time.h>
#include <assert.h>

#include <binder/IMemory.h>
#include <binder/MemoryHeapBase.h>
#include <utils/RefBase.h>

namespace Jack
{

/*!
\brief Inter process synchronization using POSIX semaphore.
*/

class SERVER_EXPORT JackAndroidSemaphore : public detail::JackSynchro
{

private:

sem_t* fSemaphore;
android::sp<android::IMemoryHeap> fSemaphoreMemory;
static pthread_mutex_t mutex;

protected:

void BuildName(const char* name, const char* server_name, char* res, int size);

public:

JackAndroidSemaphore():JackSynchro(), fSemaphore(NULL)
{}

bool Signal();
bool SignalAll();
bool Wait();
bool TimedWait(long usec);

bool Allocate(const char* name, const char* server_name, int value);
bool Connect(const char* name, const char* server_name);
bool ConnectInput(const char* name, const char* server_name);
bool ConnectOutput(const char* name, const char* server_name);
bool Disconnect();
void Destroy();
};

} // end of namespace


#endif


+ 374
- 0
android/JackAndroidThread.cpp View File

@@ -0,0 +1,374 @@
/*
Copyright (C) 2001 Paul Davis
Copyright (C) 2004-2008 Grame
Copyright (C) 2013 Samsung Electronics

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*/

#include "JackAndroidThread.h"
#include "JackError.h"
#include "JackTime.h"
#include "JackGlobals.h"
#include <string.h> // for memset
#include <unistd.h> // for _POSIX_PRIORITY_SCHEDULING check
#include <signal.h>

//#define JACK_SCHED_POLICY SCHED_RR
#define JACK_SCHED_POLICY SCHED_FIFO

namespace Jack
{

void JackAndroidThread::thread_exit_handler(int sig)
{
printf("this signal is %d \n", sig);
pthread_exit(0);
}

void* JackAndroidThread::ThreadHandler(void* arg)
{
JackAndroidThread* obj = (JackAndroidThread*)arg;
JackRunnableInterface* runnable = obj->fRunnable;
int err;

struct sigaction actions;
memset(&actions, 0, sizeof(actions));
sigemptyset(&actions.sa_mask);
actions.sa_flags = 0;
actions.sa_handler = thread_exit_handler;
sigaction(SIGUSR1,&actions,NULL);

// Signal creation thread when started with StartSync
jack_log("JackAndroidThread::ThreadHandler : start");
obj->fStatus = kIniting;

// Call Init method
if (!runnable->Init()) {
jack_error("Thread init fails: thread quits");
return 0;
}

obj->fStatus = kRunning;

// If Init succeed, start the thread loop
bool res = true;
while (obj->fStatus == kRunning && res) {
res = runnable->Execute();
}

jack_log("JackAndroidThread::ThreadHandler : exit");
pthread_exit(0);
return 0; // never reached
}

int JackAndroidThread::Start()
{
fStatus = kStarting;

// Check if the thread was correctly started
if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) {
fStatus = kIdle;
return -1;
} else {
return 0;
}
}

int JackAndroidThread::StartSync()
{
fStatus = kStarting;

if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) {
fStatus = kIdle;
return -1;
} else {
int count = 0;
while (fStatus == kStarting && ++count < 1000) {
JackSleep(1000);
}
return (count == 1000) ? -1 : 0;
}
}

int JackAndroidThread::StartImp(jack_native_thread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg)
{
pthread_attr_t attributes;
struct sched_param rt_param;
pthread_attr_init(&attributes);
int res;

if ((res = pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE))) {
jack_error("Cannot request joinable thread creation for thread res = %d", res);
return -1;
}

if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) {
jack_error("Cannot set scheduling scope for thread res = %d", res);
return -1;
}

if (realtime) {

jack_log("JackAndroidThread::StartImp : create RT thread");

if ((res = pthread_attr_setschedpolicy(&attributes, JACK_SCHED_POLICY))) {
jack_error("Cannot set RR scheduling class for RT thread res = %d", res);
return -1;
}

memset(&rt_param, 0, sizeof(rt_param));
rt_param.sched_priority = priority;

if ((res = pthread_attr_setschedparam(&attributes, &rt_param))) {
jack_error("Cannot set scheduling priority for RT thread res = %d", res);
return -1;
}

} else {
jack_log("JackAndroidThread::StartImp : create non RT thread");
}

if ((res = pthread_attr_setstacksize(&attributes, THREAD_STACK))) {
jack_error("Cannot set thread stack size res = %d", res);
return -1;
}

if ((res = JackGlobals::fJackThreadCreator(thread, &attributes, start_routine, arg))) {
jack_error("Cannot create thread res = %d", res);
return -1;
}

pthread_attr_destroy(&attributes);
return 0;
}

int JackAndroidThread::Kill()
{
if (fThread != (jack_native_thread_t)NULL) { // If thread has been started
jack_log("JackAndroidThread::Kill");
void* status;

pthread_kill(fThread, SIGUSR1);
pthread_join(fThread, &status);
fStatus = kIdle;
fThread = (jack_native_thread_t)NULL;
return 0;
} else {
return -1;
}
}

int JackAndroidThread::Stop()
{
if (fThread != (jack_native_thread_t)NULL) { // If thread has been started
jack_log("JackAndroidThread::Stop");
void* status;
fStatus = kIdle; // Request for the thread to stop
pthread_join(fThread, &status);
fThread = (jack_native_thread_t)NULL;
return 0;
} else {
return -1;
}
}

int JackAndroidThread::KillImp(jack_native_thread_t thread)
{
if (thread != (jack_native_thread_t)NULL) { // If thread has been started
jack_log("JackAndroidThread::Kill");
void* status;
pthread_kill(thread, SIGUSR1);
pthread_join(thread, &status);
return 0;
} else {
return -1;
}
}

int JackAndroidThread::StopImp(jack_native_thread_t thread)
{
if (thread != (jack_native_thread_t)NULL) { // If thread has been started
jack_log("JackAndroidThread::Stop");
void* status;
pthread_join(thread, &status);
return 0;
} else {
return -1;
}
}

int JackAndroidThread::AcquireRealTime()
{
return (fThread != (jack_native_thread_t)NULL) ? AcquireRealTimeImp(fThread, fPriority) : -1;
}

int JackAndroidThread::AcquireSelfRealTime()
{
return AcquireRealTimeImp(pthread_self(), fPriority);
}

int JackAndroidThread::AcquireRealTime(int priority)
{
fPriority = priority;
return AcquireRealTime();
}

int JackAndroidThread::AcquireSelfRealTime(int priority)
{
fPriority = priority;
return AcquireSelfRealTime();
}
int JackAndroidThread::AcquireRealTimeImp(jack_native_thread_t thread, int priority)
{
struct sched_param rtparam;
int res;
memset(&rtparam, 0, sizeof(rtparam));
rtparam.sched_priority = priority;

jack_log("JackAndroidThread::AcquireRealTimeImp priority = %d", priority);

if ((res = pthread_setschedparam(thread, JACK_SCHED_POLICY, &rtparam)) != 0) {
jack_error("Cannot use real-time scheduling (RR/%d)"
"(%d: %s)", rtparam.sched_priority, res,
strerror(res));
return -1;
}
return 0;
}

int JackAndroidThread::DropRealTime()
{
return (fThread != (jack_native_thread_t)NULL) ? DropRealTimeImp(fThread) : -1;
}

int JackAndroidThread::DropSelfRealTime()
{
return DropRealTimeImp(pthread_self());
}

int JackAndroidThread::DropRealTimeImp(jack_native_thread_t thread)
{
struct sched_param rtparam;
int res;
memset(&rtparam, 0, sizeof(rtparam));
rtparam.sched_priority = 0;

if ((res = pthread_setschedparam(thread, SCHED_OTHER, &rtparam)) != 0) {
jack_error("Cannot switch to normal scheduling priority(%s)", strerror(errno));
return -1;
}
return 0;
}

jack_native_thread_t JackAndroidThread::GetThreadID()
{
return fThread;
}

bool JackAndroidThread::IsThread()
{
return pthread_self() == fThread;
}

void JackAndroidThread::Terminate()
{
jack_log("JackAndroidThread::Terminate");
pthread_exit(0);
}

SERVER_EXPORT void ThreadExit()
{
jack_log("ThreadExit");
pthread_exit(0);
}

} // end of namespace

bool jack_get_thread_realtime_priority_range(int * min_ptr, int * max_ptr)
{
#if defined(_POSIX_PRIORITY_SCHEDULING) && !defined(__APPLE__)
int min, max;

min = sched_get_priority_min(JACK_SCHED_POLICY);
if (min == -1)
{
jack_error("sched_get_priority_min() failed.");
return false;
}

max = sched_get_priority_max(JACK_SCHED_POLICY);
if (max == -1)
{
jack_error("sched_get_priority_max() failed.");
return false;
}

*min_ptr = min;
*max_ptr = max;

return true;
#else
return false;
#endif
}

bool jack_tls_allocate_key(jack_tls_key *key_ptr)
{
int ret;

ret = pthread_key_create(key_ptr, NULL);
if (ret != 0)
{
jack_error("pthread_key_create() failed with error %d", ret);
return false;
}

return true;
}

bool jack_tls_free_key(jack_tls_key key)
{
int ret;

ret = pthread_key_delete(key);
if (ret != 0)
{
jack_error("pthread_key_delete() failed with error %d", ret);
return false;
}

return true;
}

bool jack_tls_set(jack_tls_key key, void *data_ptr)
{
int ret;

ret = pthread_setspecific(key, (const void *)data_ptr);
if (ret != 0)
{
jack_error("pthread_setspecific() failed with error %d", ret);
return false;
}

return true;
}

void *jack_tls_get(jack_tls_key key)
{
return pthread_getspecific(key);
}

+ 97
- 0
android/JackAndroidThread.h View File

@@ -0,0 +1,97 @@
/*
Copyright (C) 2001 Paul Davis
Copyright (C) 2004-2008 Grame
Copyright (C) 2013 Samsung Electronics

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*/

#ifndef __JackAndroidThread__
#define __JackAndroidThread__

#include "JackThread.h"
#include <pthread.h>

namespace Jack
{

/* use 512KB stack per thread - the default is way too high to be feasible
* with mlockall() on many systems */
#define THREAD_STACK 524288

enum
{
PTHREAD_CANCEL_DEFERRED,
PTHREAD_CANCEL_ASYNCHRONOUS
};

/*!
\brief The POSIX thread base class.
*/

class SERVER_EXPORT JackAndroidThread : public detail::JackThreadInterface
{

protected:

jack_native_thread_t fThread;
static void* ThreadHandler(void* arg);
static void thread_exit_handler(int sig);

public:

JackAndroidThread(JackRunnableInterface* runnable, bool real_time, int priority, int cancellation)
: JackThreadInterface(runnable, priority, real_time, cancellation), fThread((jack_native_thread_t)NULL)
{}
JackAndroidThread(JackRunnableInterface* runnable, int cancellation = PTHREAD_CANCEL_ASYNCHRONOUS)
: JackThreadInterface(runnable, 0, false, cancellation), fThread((jack_native_thread_t)NULL)
{}

int Start();
int StartSync();
int Kill();
int Stop();
void Terminate();

int AcquireRealTime(); // Used when called from another thread
int AcquireSelfRealTime(); // Used when called from thread itself

int AcquireRealTime(int priority); // Used when called from another thread
int AcquireSelfRealTime(int priority); // Used when called from thread itself

int DropRealTime(); // Used when called from another thread
int DropSelfRealTime(); // Used when called from thread itself

jack_native_thread_t GetThreadID();
bool IsThread();

static int AcquireRealTimeImp(jack_native_thread_t thread, int priority);
static int AcquireRealTimeImp(jack_native_thread_t thread, int priority, UInt64 period, UInt64 computation, UInt64 constraint)
{
return JackAndroidThread::AcquireRealTimeImp(thread, priority);
}
static int DropRealTimeImp(jack_native_thread_t thread);
static int StartImp(jack_native_thread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg);
static int StopImp(jack_native_thread_t thread);
static int KillImp(jack_native_thread_t thread);
};

SERVER_EXPORT void ThreadExit();

} // end of namespace


#endif

+ 42
- 0
android/JackAtomic_os.h View File

@@ -0,0 +1,42 @@
/*
Copyright (C) 2004-2008 Grame
Copyright (C) 2013 Samsung Electronics

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*/

#ifndef __JackAtomic_android__
#define __JackAtomic_android__

#include "JackTypes.h"

#include <sys/atomics.h>
static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr)
{
#if 1
return !__atomic_cmpxchg(value, newvalue, (volatile int *)addr);
#else
//slow compare_and_swap_32
if (*(UInt32*)addr == value) {
*(UInt32*)addr = newvalue;
return true;
}
return false;
#endif
}

#endif


+ 48
- 0
android/JackCompilerDeps_os.h View File

@@ -0,0 +1,48 @@
/*
Copyright (C) 2004-2008 Grame
Copyright (C) 2013 Samsung Electronics

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*/

#ifndef __JackCompilerDeps_android__
#define __JackCompilerDeps_android__

#include "JackConstants.h"

#if __GNUC__

#define MEM_ALIGN(x,y) x __attribute__((aligned(y)))
#define LIB_EXPORT __attribute__((visibility("default")))
#ifdef SERVER_SIDE
#if (__GNUC__< 4)
#define SERVER_EXPORT
#else
#define SERVER_EXPORT __attribute__((visibility("default")))
#endif
#else
#define SERVER_EXPORT __attribute__((visibility("hidden")))
#endif
#else
#define MEM_ALIGN(x,y) x
#define LIB_EXPORT
#define SERVER_EXPORT

/* Add other things here for non-gcc platforms */
#endif

#endif /* __JackCompilerDeps_android__ */

+ 89
- 0
android/JackControlAPIAndroid.cpp View File

@@ -0,0 +1,89 @@
// u/* -*- Mode: C++ ; c-basic-offset: 4 -*- */
/*
JACK control API implementation

Copyright (C) 2008 Nedko Arnaudov
Copyright (C) 2008 Grame
Copyright (C) 2013 Samsung Electronics

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#ifndef WIN32
#include <stdint.h>
#include <dirent.h>
#include <pthread.h>
#endif

#include "types.h"
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <assert.h>
#include <signal.h>

#include "JackControlAPIAndroid.h"
#include "JackConstants.h"
#include "JackServerGlobals.h"

using namespace Jack;

struct jackctl_sigmask
{
sigset_t signals;
};

static jackctl_sigmask sigmask;

SERVER_EXPORT int
jackctl_wait_signals_and_return(jackctl_sigmask_t * sigmask)
{
int sig;
bool waiting = true;

while (waiting) {
#if defined(sun) && !defined(__sun__) // SUN compiler only, to check
sigwait(&sigmask->signals);
#else
sigwait(&sigmask->signals, &sig);
#endif
fprintf(stderr, "Jack main caught signal %d\n", sig);

switch (sig) {
case SIGUSR1:
//jack_dump_configuration(engine, 1);
break;
case SIGUSR2:
// driver exit
waiting = false;
break;
case SIGTTOU:
break;
default:
waiting = false;
break;
}
}

if (sig != SIGSEGV) {
// unblock signals so we can see them during shutdown.
// this will help prod developers not to lose sight of
// bugs that cause segfaults etc. during shutdown.
sigprocmask(SIG_UNBLOCK, &sigmask->signals, 0);
}

return sig;
}


+ 44
- 0
android/JackControlAPIAndroid.h View File

@@ -0,0 +1,44 @@
/*
JACK control API

Copyright (C) 2008 Nedko Arnaudov
Copyright (C) 2008 Grame
Copyright (C) 2013 Samsung Electronics

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#ifndef __JackControlAPIAndroid__
#define __JackControlAPIAndroid__

#include "JackCompilerDeps.h"

/** opaque type for sigmask object */
typedef struct jackctl_sigmask jackctl_sigmask_t;

#ifdef __cplusplus
extern "C" {
#endif

SERVER_EXPORT int