1
0
Fork 0
forked from len0rd/rockbox

Code style changes in the java part (whitespaces and braces) to match Rockbox coding style.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28065 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Thomas Martitz 2010-09-12 19:56:13 +00:00
parent 54c838d2ae
commit 282adacb54
5 changed files with 549 additions and 528 deletions

View file

@ -29,7 +29,8 @@ import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
public class RockboxActivity extends Activity {
public class RockboxActivity extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
@ -49,71 +50,75 @@ public class RockboxActivity extends Activity {
*
* In order to get the fb, we need to let the Service start up
* run, we can wait in a separate thread for fb to get ready
* This thread waits for the fb to become ready */
* This thread waits for the fb to become ready */
new Thread(new Runnable()
{
public void run() {
try {
while (RockboxService.fb == null)
Thread.sleep(250);
} catch (InterruptedException e) {
} catch (Exception e) {
LOG(e.toString());
}
/* drawing needs to happen in ui thread */
runOnUiThread(new Runnable()
{ @Override
public void run() {
setContentView(RockboxService.fb);
RockboxService.fb.invalidate();
}
});
}
public void run()
{
try {
while (RockboxService.fb == null)
Thread.sleep(250);
} catch (InterruptedException e) {
} catch (Exception e) {
LOG(e.toString());
}
/* drawing needs to happen in ui thread */
runOnUiThread(new Runnable()
{ @Override
public void run() {
setContentView(RockboxService.fb);
RockboxService.fb.invalidate();
}
});
}
}).start();
}
public void onResume()
{
super.onResume();
if (RockboxService.fb != null)
{
try {
setContentView(RockboxService.fb);
} catch (IllegalStateException e) {
/* we are already using the View,
* need to remove it and re-attach it */
ViewGroup g = (ViewGroup)RockboxService.fb.getParent();
g.removeView(RockboxService.fb);
setContentView(RockboxService.fb);
}
RockboxService.fb.resume();
}
super.onResume();
if (RockboxService.fb != null)
{
try {
setContentView(RockboxService.fb);
} catch (IllegalStateException e) {
/* we are already using the View,
* need to remove it and re-attach it */
ViewGroup g = (ViewGroup)RockboxService.fb.getParent();
g.removeView(RockboxService.fb);
setContentView(RockboxService.fb);
}
RockboxService.fb.resume();
}
}
/* this is also called when the backlight goes off,
* which is nice
*/
@Override
protected void onPause() {
super.onPause();
RockboxService.fb.suspend();
protected void onPause()
{
super.onPause();
RockboxService.fb.suspend();
}
@Override
protected void onStop() {
super.onStop();
RockboxService.fb.suspend();
protected void onStop()
{
super.onStop();
RockboxService.fb.suspend();
}
@Override
protected void onDestroy() {
super.onDestroy();
RockboxService.fb.suspend();
protected void onDestroy()
{
super.onDestroy();
RockboxService.fb.suspend();
}
private void LOG(CharSequence text)
{
Log.d("Rockbox", (String) text);
}
private void LOG(CharSequence text)
{
Log.d("Rockbox", (String) text);
}
}

View file

@ -33,93 +33,92 @@ import android.view.View;
public class RockboxFramebuffer extends View
{
private Bitmap btm;
private Bitmap btm;
private ByteBuffer native_buf;
public RockboxFramebuffer(Context c)
{
super(c);
btm = null;
public RockboxFramebuffer(Context c)
{
super(c);
btm = null;
/* Needed so we can catch KeyEvents */
setFocusable(true);
requestFocus();
}
/* Needed so we can catch KeyEvents */
setFocusable(true);
requestFocus();
}
public void onDraw(Canvas c)
{
if (btm != null)
c.drawBitmap(btm, 0.0f, 0.0f, null);
}
public void java_lcd_init(int lcd_width, int lcd_height, ByteBuffer native_fb)
{
btm = Bitmap.createBitmap(lcd_width, lcd_height, Bitmap.Config.RGB_565);
native_buf = native_fb;
}
public void java_lcd_update()
{
btm.copyPixelsFromBuffer(native_buf);
postInvalidate();
}
public void java_lcd_update_rect(int x, int y, int w, int h)
{
/* can't copy a partial buffer */
btm.copyPixelsFromBuffer(native_buf);
public void onDraw(Canvas c)
{
if (btm != null)
c.drawBitmap(btm, 0.0f, 0.0f, null);
}
public void java_lcd_init(int lcd_width, int lcd_height, ByteBuffer native_fb)
{
btm = Bitmap.createBitmap(lcd_width, lcd_height, Bitmap.Config.RGB_565);
native_buf = native_fb;
}
public void java_lcd_update()
{
btm.copyPixelsFromBuffer(native_buf);
postInvalidate();
}
public void java_lcd_update_rect(int x, int y, int w, int h)
{
/* can't copy a partial buffer */
btm.copyPixelsFromBuffer(native_buf);
postInvalidate(x, y, x+w, y+h);
}
postInvalidate(x, y, x+w, y+h);
}
@SuppressWarnings("unused")
private void LOG(CharSequence text)
{
Log.d("Rockbox", (String) text);
}
@SuppressWarnings("unused")
private void LOG(CharSequence text)
{
Log.d("Rockbox", (String) text);
}
public boolean onTouchEvent(MotionEvent me)
{
public boolean onTouchEvent(MotionEvent me)
{
int x = (int) me.getX();
int y = (int) me.getY();
switch (me.getAction())
{
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
touchHandler(false, x, y);
return true;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_DOWN:
touchHandler(true, x, y);
return true;
}
switch (me.getAction())
{
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
touchHandler(false, x, y);
return true;
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_DOWN:
touchHandler(true, x, y);
return true;
}
return false;
}
return false;
}
public boolean onKeyDown(int keyCode, KeyEvent event)
{
return buttonHandler(keyCode, true);
}
public boolean onKeyDown(int keyCode, KeyEvent event)
{
return buttonHandler(keyCode, true);
}
public boolean onKeyUp(int keyCode, KeyEvent event)
{
return buttonHandler(keyCode, false);
}
public boolean onKeyUp(int keyCode, KeyEvent event)
{
return buttonHandler(keyCode, false);
}
/* the two below should only be called from the activity thread */
public void suspend()
{ /* suspend, Rockbox will not make any lcd updates */
set_lcd_active(0);
}
public void resume()
{ /* make updates again, the underlying function will
* send an event */
set_lcd_active(1);
}
/* the two below should only be called from the activity thread */
public void suspend()
{ /* suspend, Rockbox will not make any lcd updates */
set_lcd_active(0);
}
public void resume()
{ /* make updates again, the underlying function will
* send an event */
set_lcd_active(1);
}
public native void set_lcd_active(int active);
public native void touchHandler(boolean down, int x, int y);
public native boolean buttonHandler(int keycode, boolean state);
public native void set_lcd_active(int active);
public native void touchHandler(boolean down, int x, int y);
public native boolean buttonHandler(int keycode, boolean state);
}

View file

@ -33,142 +33,148 @@ import android.util.Log;
public class RockboxPCM extends AudioTrack
{
private byte[] raw_data;
private PCMListener l;
private HandlerThread ht;
private Handler h = null;
private static final int samplerate = 44100;
private byte[] raw_data;
private PCMListener l;
private HandlerThread ht;
private Handler h = null;
private static final int samplerate = 44100;
/* should be CHANNEL_OUT_STEREO in 2.0 and above */
private static final int channels = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
private static final int encoding = AudioFormat.ENCODING_PCM_16BIT;
private static final int buf_len = getMinBufferSize(44100, channels, encoding);
private static final int channels = AudioFormat.CHANNEL_CONFIGURATION_STEREO;
private static final int encoding = AudioFormat.ENCODING_PCM_16BIT;
private static final int buf_len = getMinBufferSize(44100, channels, encoding);
private void LOG(CharSequence text)
{
Log.d("Rockbox", (String) text);
}
private void LOG(CharSequence text)
{
Log.d("Rockbox", (String) text);
}
public RockboxPCM()
{
super(AudioManager.STREAM_MUSIC, samplerate, channels, encoding,
buf_len, AudioTrack.MODE_STREAM);
ht = new HandlerThread("audio thread", Process.THREAD_PRIORITY_URGENT_AUDIO);
ht.start();
raw_data = new byte[buf_len]; /* in shorts */
Arrays.fill(raw_data, (byte) 0);
l = new PCMListener(buf_len);
}
public RockboxPCM()
{
super(AudioManager.STREAM_MUSIC, samplerate, channels, encoding,
buf_len, AudioTrack.MODE_STREAM);
ht = new HandlerThread("audio thread", Process.THREAD_PRIORITY_URGENT_AUDIO);
ht.start();
raw_data = new byte[buf_len]; /* in shorts */
Arrays.fill(raw_data, (byte) 0);
l = new PCMListener(buf_len);
}
int bytes2frames(int bytes) {
/* 1 sample is 2 bytes, 2 samples are 1 frame */
return (bytes/4);
}
int frames2bytes(int frames) {
/* 1 frame is 2 samples, 1 sample is 2 bytes */
return (frames*4);
}
private int bytes2frames(int bytes)
{
/* 1 sample is 2 bytes, 2 samples are 1 frame */
return (bytes/4);
}
private int frames2bytes(int frames)
{
/* 1 frame is 2 samples, 1 sample is 2 bytes */
return (frames*4);
}
@SuppressWarnings("unused")
private void play_pause(boolean pause) {
if (pause)
{
pause();
}
else
{
if (getPlayState() == AudioTrack.PLAYSTATE_STOPPED)
{
RockboxService.startForeground();
if (getState() == AudioTrack.STATE_INITIALIZED)
{
if (h == null)
h = new Handler(ht.getLooper());
if (setNotificationMarkerPosition(bytes2frames(buf_len)/4) != AudioTrack.SUCCESS)
LOG("setNotificationMarkerPosition Error");
else
setPlaybackPositionUpdateListener(l, h);
}
/* need to fill with silence before starting playback */
write(raw_data, frames2bytes(getPlaybackHeadPosition()), raw_data.length);
}
play();
}
private void play_pause(boolean pause) {
if (pause)
{
pause();
}
else
{
if (getPlayState() == AudioTrack.PLAYSTATE_STOPPED)
{
RockboxService.startForeground();
if (getState() == AudioTrack.STATE_INITIALIZED)
{
if (h == null)
h = new Handler(ht.getLooper());
if (setNotificationMarkerPosition(bytes2frames(buf_len)/4) != AudioTrack.SUCCESS)
LOG("setNotificationMarkerPosition Error");
else
setPlaybackPositionUpdateListener(l, h);
}
/* need to fill with silence before starting playback */
write(raw_data, frames2bytes(getPlaybackHeadPosition()), raw_data.length);
}
play();
}
}
@Override
public void stop() throws IllegalStateException
{
try {
super.stop();
} catch (IllegalStateException e) {
throw new IllegalStateException(e);
}
RockboxService.stopForeground();
try {
super.stop();
} catch (IllegalStateException e) {
throw new IllegalStateException(e);
}
RockboxService.stopForeground();
}
@SuppressWarnings("unused")
private void set_volume(int volume)
{
/* volume comes from 0..-990 from Rockbox */
/* TODO volume is in dB, but this code acts as if it were in %, convert? */
float fvolume;
/* special case min and max volume to not suffer from floating point accuracy */
if (volume == 0)
fvolume = 1.0f;
else if (volume == -990)
fvolume = 0.0f;
else
fvolume = (volume + 990)/990.0f;
setStereoVolume(fvolume, fvolume);
/* volume comes from 0..-990 from Rockbox */
/* TODO volume is in dB, but this code acts as if it were in %, convert? */
float fvolume;
/* special case min and max volume to not suffer from floating point accuracy */
if (volume == 0)
fvolume = 1.0f;
else if (volume == -990)
fvolume = 0.0f;
else
fvolume = (volume + 990)/990.0f;
setStereoVolume(fvolume, fvolume);
}
public native void pcmSamplesToByteArray(byte[] dest);
private class PCMListener implements OnPlaybackPositionUpdateListener {
int max_len;
int refill_mark;
byte[] buf;
public PCMListener(int len) {
private class PCMListener implements OnPlaybackPositionUpdateListener
{
private int max_len;
private int refill_mark;
private byte[] buf;
public PCMListener(int len)
{
max_len = len;
/* refill to 100% when reached the 25% */
buf = new byte[max_len*3/4];
refill_mark = max_len - buf.length;
}
@Override
public void onMarkerReached(AudioTrack track) {
/* push new data to the hardware */
RockboxPCM pcm = (RockboxPCM)track;
int result = -1;
pcm.pcmSamplesToByteArray(buf);
result = track.write(buf, 0, buf.length);
if (result >= 0)
{
switch(track.getPlayState())
{
case AudioTrack.PLAYSTATE_PLAYING:
case AudioTrack.PLAYSTATE_PAUSED:
/* refill at 25% no matter of how many bytes we've written */
if (setNotificationMarkerPosition(bytes2frames(refill_mark)) != AudioTrack.SUCCESS)
LOG("Error in onMarkerReached: Could not set notification marker");
else /* recharge */
setPlaybackPositionUpdateListener(this, h);
break;
case AudioTrack.PLAYSTATE_STOPPED:
LOG("State STOPPED");
break;
}
}
else
{
LOG("Error in onMarkerReached (result="+result+")");
stop();
}
}
}
@Override
public void onMarkerReached(AudioTrack track)
{
/* push new data to the hardware */
RockboxPCM pcm = (RockboxPCM)track;
int result = -1;
pcm.pcmSamplesToByteArray(buf);
result = track.write(buf, 0, buf.length);
if (result >= 0)
{
switch(track.getPlayState())
{
case AudioTrack.PLAYSTATE_PLAYING:
case AudioTrack.PLAYSTATE_PAUSED:
/* refill at 25% no matter of how many bytes we've written */
if (setNotificationMarkerPosition(bytes2frames(refill_mark))
!= AudioTrack.SUCCESS)
LOG("Error in onMarkerReached: Could not set notification marker");
else /* recharge */
setPlaybackPositionUpdateListener(this, h);
break;
case AudioTrack.PLAYSTATE_STOPPED:
LOG("State STOPPED");
break;
}
}
else
{
LOG("Error in onMarkerReached (result="+result+")");
stop();
}
}
@Override
public void onPeriodicNotification(AudioTrack track) {
// TODO Auto-generated method stub
}
}
@Override
public void onPeriodicNotification(AudioTrack track)
{
}
}
}

View file

@ -48,78 +48,82 @@ import android.util.Log;
public class RockboxService extends Service
{
/* this Service is really a singleton class */
public static RockboxFramebuffer fb = null;
private static RockboxService instance;
private Notification notification;
private static final Class<?>[] mStartForegroundSignature = new Class[] {
int.class, Notification.class};
private static final Class<?>[] mStopForegroundSignature = new Class[] {
boolean.class};
/* this Service is really a singleton class */
public static RockboxFramebuffer fb = null;
private static RockboxService instance;
private Notification notification;
private static final Class<?>[] mStartForegroundSignature = new Class[] {
int.class, Notification.class};
private static final Class<?>[] mStopForegroundSignature = new Class[] {
boolean.class};
private NotificationManager mNM;
private Method mStartForeground;
private Method mStopForeground;
private Object[] mStartForegroundArgs = new Object[2];
private Object[] mStopForegroundArgs = new Object[1];
private IntentFilter itf;
private BroadcastReceiver batt_monitor;
private int battery_level;
@Override
public void onCreate()
{
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
try {
mStartForeground = getClass().getMethod("startForeground",
mStartForegroundSignature);
mStopForeground = getClass().getMethod("stopForeground",
mStopForegroundSignature);
} catch (NoSuchMethodException e) {
/* Running on an older platform: fall back to old API */
mStartForeground = mStopForeground = null;
}
startservice();
instance = this;
}
private NotificationManager mNM;
private Method mStartForeground;
private Method mStopForeground;
private Object[] mStartForegroundArgs = new Object[2];
private Object[] mStopForegroundArgs = new Object[1];
private IntentFilter itf;
private BroadcastReceiver batt_monitor;
private int battery_level;
private void do_start(Intent intent)
{
LOG("Start Service");
/* Display a notification about us starting. We put an icon in the status bar. */
create_notification();
}
@Override
public void onCreate()
{
mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
try
{
mStartForeground = getClass().getMethod("startForeground",
mStartForegroundSignature);
mStopForeground = getClass().getMethod("stopForeground",
mStopForegroundSignature);
}
catch (NoSuchMethodException e)
{
/* Running on an older platform: fall back to old API */
mStartForeground = mStopForeground = null;
}
startservice();
instance = this;
}
private void LOG(CharSequence text)
{
Log.d("Rockbox", (String) text);
}
private void LOG(CharSequence text, Throwable tr)
{
Log.d("Rockbox", (String) text, tr);
}
private void do_start(Intent intent)
{
LOG("Start Service");
/* Display a notification about us starting. We put an icon in the status bar. */
create_notification();
}
public void onStart(Intent intent, int startId) {
do_start(intent);
}
private void LOG(CharSequence text)
{
Log.d("Rockbox", (String) text);
}
private void LOG(CharSequence text, Throwable tr)
{
Log.d("Rockbox", (String) text, tr);
}
public int onStartCommand(Intent intent, int flags, int startId)
{
do_start(intent);
return 1; /* old API compatibility: 1 == START_STICKY */
}
public void onStart(Intent intent, int startId) {
do_start(intent);
}
private void startservice()
{
public int onStartCommand(Intent intent, int flags, int startId)
{
do_start(intent);
return 1; /* old API compatibility: 1 == START_STICKY */
}
private void startservice()
{
fb = new RockboxFramebuffer(this);
final int BUFFER = 8*1024;
/* the following block unzips libmisc.so, which contains the files
* we ship, such as themes. It's needed to put it into a .so file
* because there's no other way to ship files and have access
* to them from native code
*/
try
{
final int BUFFER = 8*1024;
/* the following block unzips libmisc.so, which contains the files
* we ship, such as themes. It's needed to put it into a .so file
* because there's no other way to ship files and have access
* to them from native code
*/
try
{
BufferedOutputStream dest = null;
BufferedInputStream is = null;
ZipEntry entry;
@ -128,112 +132,115 @@ public class RockboxService extends Service
File file2 = new File("/data/data/org.rockbox/app_rockbox/rockbox/codecs/mpa.codec");
if (!file2.exists() || (file.lastModified() > file2.lastModified()))
{
ZipFile zipfile = new ZipFile(file);
Enumeration<? extends ZipEntry> e = zipfile.entries();
File folder;
while(e.hasMoreElements()) {
entry = (ZipEntry) e.nextElement();
LOG("Extracting: " +entry);
if (entry.isDirectory())
{
folder = new File(entry.getName());
LOG("mkdir "+ entry);
try {
folder.mkdirs();
} catch (SecurityException ex){
LOG(ex.getMessage());
}
continue;
}
is = new BufferedInputStream(zipfile.getInputStream(entry), BUFFER);
int count;
byte data[] = new byte[BUFFER];
folder = new File(new File(entry.getName()).getParent());
LOG("" + folder.getAbsolutePath());
if (!folder.exists())
folder.mkdirs();
FileOutputStream fos = new FileOutputStream(entry.getName());
dest = new BufferedOutputStream(fos, BUFFER);
while ((count = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, count);
}
dest.flush();
dest.close();
is.close();
}
ZipFile zipfile = new ZipFile(file);
Enumeration<? extends ZipEntry> e = zipfile.entries();
File folder;
while(e.hasMoreElements())
{
entry = (ZipEntry) e.nextElement();
LOG("Extracting: " +entry);
if (entry.isDirectory())
{
folder = new File(entry.getName());
LOG("mkdir "+ entry);
try {
folder.mkdirs();
} catch (SecurityException ex) {
LOG(ex.getMessage());
}
continue;
}
is = new BufferedInputStream(zipfile.getInputStream(entry), BUFFER);
int count;
byte data[] = new byte[BUFFER];
folder = new File(new File(entry.getName()).getParent());
LOG("" + folder.getAbsolutePath());
if (!folder.exists())
folder.mkdirs();
FileOutputStream fos = new FileOutputStream(entry.getName());
dest = new BufferedOutputStream(fos, BUFFER);
while ((count = is.read(data, 0, BUFFER)) != -1)
dest.write(data, 0, count);
dest.flush();
dest.close();
is.close();
}
}
} catch(FileNotFoundException e) {
LOG("FileNotFoundException when unzipping", e);
e.printStackTrace();
LOG("FileNotFoundException when unzipping", e);
e.printStackTrace();
} catch(IOException e) {
LOG("IOException when unzipping", e);
e.printStackTrace();
LOG("IOException when unzipping", e);
e.printStackTrace();
}
System.loadLibrary("rockbox");
Thread rb = new Thread(new Runnable()
{
public void run()
{
main();
}
},"Rockbox thread");
rb.setDaemon(false);
rb.start();
}
Thread rb = new Thread(new Runnable()
{
public void run()
{
main();
}
},"Rockbox thread");
rb.setDaemon(false);
rb.start();
}
private native void main();
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
@Override
public IBinder onBind(Intent intent)
{
// TODO Auto-generated method stub
return null;
}
@SuppressWarnings("unused")
/*
* Sets up the battery monitor which receives the battery level
* about each 30 seconds
*/
private void initBatteryMonitor()
{
itf = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
batt_monitor = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
/* we get literally spammed with battery statuses
* if we don't delay the re-attaching
*/
TimerTask tk = new TimerTask() {
public void run() {
registerReceiver(batt_monitor, itf);
}
};
Timer t = new Timer();
context.unregisterReceiver(this);
int rawlevel = intent.getIntExtra("level", -1);
int scale = intent.getIntExtra("scale", -1);
if (rawlevel >= 0 && scale > 0)
battery_level = (rawlevel * 100) / scale;
else
battery_level = -1;
/* query every 30s should be sufficient */
t.schedule(tk, 30000);
}
};
registerReceiver(batt_monitor, itf);
}
@SuppressWarnings("unused")
/*
* Sets up the battery monitor which receives the battery level
* about each 30 seconds
*/
private void initBatteryMonitor()
{
itf = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
batt_monitor = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
/* we get literally spammed with battery statuses
* if we don't delay the re-attaching
*/
TimerTask tk = new TimerTask()
{
public void run()
{
registerReceiver(batt_monitor, itf);
}
};
Timer t = new Timer();
context.unregisterReceiver(this);
int rawlevel = intent.getIntExtra("level", -1);
int scale = intent.getIntExtra("scale", -1);
if (rawlevel >= 0 && scale > 0)
battery_level = (rawlevel * 100) / scale;
else
battery_level = -1;
/* query every 30s should be sufficient */
t.schedule(tk, 30000);
}
};
registerReceiver(batt_monitor, itf);
}
/* all below is heavily based on the examples found on
* http://developer.android.com/reference/android/app/Service.html
*/
private void create_notification()
{
/* For now we'll use the same text for the ticker and the expanded notification */
/* For now we'll use the same text for the ticker and the expanded notification */
CharSequence text = getText(R.string.notification);
/* Set the icon, scrolling text and timestamp */
notification = new Notification(R.drawable.icon, text,
@ -247,89 +254,90 @@ public class RockboxService extends Service
notification.setLatestEventInfo(this, getText(R.string.notification), text, contentIntent);
}
public static void startForeground()
{
if (instance != null)
{
/*
* Send the notification.
* We use a layout id because it is a unique number. We use it later to cancel.
*/
instance.mNM.notify(R.string.notification, instance.notification);
/*
* this call makes the service run as foreground, which
* provides enough cpu time to do music decoding in the
* background
*/
instance.startForegroundCompat(R.string.notification, instance.notification);
}
}
public static void stopForeground()
{
if (instance.notification != null)
{
instance.stopForegroundCompat(R.string.notification);
instance.mNM.cancel(R.string.notification);
}
}
public static void startForeground()
{
if (instance != null)
{
/*
* Send the notification.
* We use a layout id because it is a unique number. We use it later to cancel.
*/
instance.mNM.notify(R.string.notification, instance.notification);
/*
* this call makes the service run as foreground, which
* provides enough cpu time to do music decoding in the
* background
*/
instance.startForegroundCompat(R.string.notification, instance.notification);
}
}
public static void stopForeground()
{
if (instance.notification != null)
{
instance.stopForegroundCompat(R.string.notification);
instance.mNM.cancel(R.string.notification);
}
}
/**
* This is a wrapper around the new startForeground method, using the older
* APIs if it is not available.
*/
void startForegroundCompat(int id, Notification notification)
{
if (mStartForeground != null) {
mStartForegroundArgs[0] = Integer.valueOf(id);
mStartForegroundArgs[1] = notification;
try {
mStartForeground.invoke(this, mStartForegroundArgs);
} catch (InvocationTargetException e) {
/* Should not happen. */
LOG("Unable to invoke startForeground", e);
} catch (IllegalAccessException e) {
/* Should not happen. */
LOG("Unable to invoke startForeground", e);
}
return;
}
/**
* This is a wrapper around the new startForeground method, using the older
* APIs if it is not available.
*/
void startForegroundCompat(int id, Notification notification)
{
if (mStartForeground != null) {
mStartForegroundArgs[0] = Integer.valueOf(id);
mStartForegroundArgs[1] = notification;
try {
mStartForeground.invoke(this, mStartForegroundArgs);
} catch (InvocationTargetException e) {
/* Should not happen. */
LOG("Unable to invoke startForeground", e);
} catch (IllegalAccessException e) {
/* Should not happen. */
LOG("Unable to invoke startForeground", e);
}
return;
}
/* Fall back on the old API.*/
setForeground(true);
mNM.notify(id, notification);
}
/* Fall back on the old API.*/
setForeground(true);
mNM.notify(id, notification);
}
/**
* This is a wrapper around the new stopForeground method, using the older
* APIs if it is not available.
*/
void stopForegroundCompat(int id)
{
if (mStopForeground != null) {
mStopForegroundArgs[0] = Boolean.TRUE;
try {
mStopForeground.invoke(this, mStopForegroundArgs);
} catch (InvocationTargetException e) {
/* Should not happen. */
LOG("Unable to invoke stopForeground", e);
} catch (IllegalAccessException e) {
/* Should not happen. */
LOG("Unable to invoke stopForeground", e);
}
return;
}
/**
* This is a wrapper around the new stopForeground method, using the older
* APIs if it is not available.
*/
void stopForegroundCompat(int id)
{
if (mStopForeground != null) {
mStopForegroundArgs[0] = Boolean.TRUE;
try {
mStopForeground.invoke(this, mStopForegroundArgs);
} catch (InvocationTargetException e) {
/* Should not happen. */
LOG("Unable to invoke stopForeground", e);
} catch (IllegalAccessException e) {
/* Should not happen. */
LOG("Unable to invoke stopForeground", e);
}
return;
}
/* Fall back on the old API. Note to cancel BEFORE changing the
* foreground state, since we could be killed at that point. */
mNM.cancel(id);
setForeground(false);
}
/* Fall back on the old API. Note to cancel BEFORE changing the
* foreground state, since we could be killed at that point. */
mNM.cancel(id);
setForeground(false);
}
@Override
public void onDestroy() {
super.onDestroy();
/* Make sure our notification is gone. */
stopForegroundCompat(R.string.notification);
}
@Override
public void onDestroy()
{
super.onDestroy();
/* Make sure our notification is gone. */
stopForegroundCompat(R.string.notification);
}
}

View file

@ -30,70 +30,73 @@ import android.util.Log;
public class RockboxTimer extends Timer
{
RockboxTimerTask task;
long interval;
private class RockboxTimerTask extends TimerTask {
private RockboxTimer t;
private TelephonyManager tm;
private int last_state;
public RockboxTimerTask(RockboxService s, RockboxTimer parent) {
super();
t = parent;
tm = (TelephonyManager)s.getSystemService(Context.TELEPHONY_SERVICE);
last_state = tm.getCallState();
}
RockboxTimerTask task;
long interval;
private class RockboxTimerTask extends TimerTask {
private RockboxTimer t;
private TelephonyManager tm;
private int last_state;
public RockboxTimerTask(RockboxService s, RockboxTimer parent) {
super();
t = parent;
tm = (TelephonyManager)s.getSystemService(Context.TELEPHONY_SERVICE);
last_state = tm.getCallState();
}
@Override
public void run() {
timerTask();
int state = tm.getCallState();
if (state != last_state)
{
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
postCallHungUp();
break;
case TelephonyManager.CALL_STATE_RINGING:
postCallIncoming();
default:
break;
}
last_state = state;
}
synchronized(t) {
t.notify();
}
}
}
public RockboxTimer(RockboxService instance, long period_inverval_in_ms)
{
super("tick timer", false);
task = new RockboxTimerTask(instance, this);
schedule(task, 0, period_inverval_in_ms);
interval = period_inverval_in_ms;
}
@Override
public void run()
{
timerTask();
int state = tm.getCallState();
if (state != last_state)
{
switch (state)
{
case TelephonyManager.CALL_STATE_IDLE:
postCallHungUp();
break;
case TelephonyManager.CALL_STATE_RINGING:
postCallIncoming();
default:
break;
}
last_state = state;
}
synchronized(t) {
t.notify();
}
}
}
public RockboxTimer(RockboxService instance, long period_inverval_in_ms)
{
super("tick timer");
task = new RockboxTimerTask(instance, this);
schedule(task, 0, period_inverval_in_ms);
interval = period_inverval_in_ms;
}
@SuppressWarnings("unused")
private void LOG(CharSequence text)
{
Log.d("Rockbox", (String) text);
}
@SuppressWarnings("unused")
private void LOG(CharSequence text)
{
Log.d("Rockbox", (String) text);
}
/* methods called from native, keep them simple */
public void java_wait_for_interrupt()
{
synchronized(this) {
try {
this.wait();
} catch (InterruptedException e) {
/* Not an error: wakeup and return */
}
}
synchronized(this)
{
try {
this.wait();
} catch (InterruptedException e) {
/* Not an error: wakeup and return */
}
}
}
public native void timerTask();
private native void postCallIncoming();
private native void postCallHungUp();
public native void timerTask();
private native void postCallIncoming();
private native void postCallHungUp();
}