-android: acquisition of WakeLock to prevent CPU throttling when display is off.

This commit is contained in:
Joachim Fritzsch 2013-04-06 12:55:00 +02:00
parent 5b701ef9e0
commit 96f3bdf16b
3 changed files with 45 additions and 6 deletions

View File

@ -29,6 +29,7 @@
<uses-sdk android:minSdkVersion="9" /> <uses-sdk android:minSdkVersion="9" />
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application <application
android:icon="@drawable/boinc" android:icon="@drawable/boinc"

View File

@ -22,6 +22,8 @@ import java.util.ArrayList;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log; import android.util.Log;
import edu.berkeley.boinc.rpc.CcStatus; import edu.berkeley.boinc.rpc.CcStatus;
import edu.berkeley.boinc.rpc.GlobalPreferences; import edu.berkeley.boinc.rpc.GlobalPreferences;
@ -40,6 +42,9 @@ public class ClientStatus {
private final String TAG = "BOINC Client Status"; private final String TAG = "BOINC Client Status";
private Context ctx; // application context in order to fire broadcast events private Context ctx; // application context in order to fire broadcast events
//WakeLock
WakeLock wakeLock;
//RPC wrapper //RPC wrapper
private CcStatus status; private CcStatus status;
private ArrayList<Result> results; private ArrayList<Result> results;
@ -75,6 +80,33 @@ public class ClientStatus {
public Integer networkSuspendReason = 0; //reason why network activity got suspended, only if NETWORK_STATUS_SUSPENDED public Integer networkSuspendReason = 0; //reason why network activity got suspended, only if NETWORK_STATUS_SUSPENDED
private Boolean networkParseError = false; //indicates that status could not be parsed and is therefore invalid private Boolean networkParseError = false; //indicates that status could not be parsed and is therefore invalid
public ClientStatus(Context ctx) {
this.ctx = ctx;
// set up Wake Lock
// see documentation at http://developer.android.com/reference/android/os/PowerManager.html
PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
wakeLock.setReferenceCounted(false); // "one call to release() is sufficient to undo the effect of all previous calls to acquire()"
}
// call to acquire or release resources held by the WakeLock.
// acquisition: every time the Monitor loop calls setClientStatus and computingStatus == COMPUTING_STATUS_COMPUTING
// release: every time computingStatus != COMPUTING_STATUS_COMPUTING , and in Monitor.onDestroy()
public void setWakeLock(Boolean acquire) {
try {
if(wakeLock.isHeld() == acquire) return; // wakeLock already in desired state
if(acquire) { // acquire wakeLock
wakeLock.acquire();
Log.d(TAG, "wakeLock acquired");
} else { // release wakeLock
wakeLock.release();
Log.d(TAG, "wakeLock released");
}
} catch (Exception e) {Log.w(TAG, "Exception durign setWakeLock " + acquire, e);}
}
/* /*
* fires "clientstatuschange" broadcast, so registered Activities can update their model. * fires "clientstatuschange" broadcast, so registered Activities can update their model.
*/ */
@ -90,10 +122,10 @@ public class ClientStatus {
/* /*
* Application context is required by the broadcast mechanism, reference is copied by Monitor service on start up. * Application context is required by the broadcast mechanism, reference is copied by Monitor service on start up.
*/
public synchronized void setCtx(Context tctx) { public synchronized void setCtx(Context tctx) {
this.ctx = tctx; this.ctx = tctx;
} }*/
/* /*
* called frequently by Monitor to set the RPC data. These objects are used to determine the client status and parse it in the data model of this class. * called frequently by Monitor to set the RPC data. These objects are used to determine the client status and parse it in the data model of this class.
@ -220,12 +252,14 @@ public class ClientStatus {
computingStatus = COMPUTING_STATUS_NEVER; computingStatus = COMPUTING_STATUS_NEVER;
computingSuspendReason = status.task_suspend_reason; // = 4 - SUSPEND_REASON_USER_REQ???? computingSuspendReason = status.task_suspend_reason; // = 4 - SUSPEND_REASON_USER_REQ????
computingParseError = false; computingParseError = false;
setWakeLock(false);
return; return;
} }
if((status.task_mode == BOINCDefs.RUN_MODE_AUTO) && (status.task_suspend_reason != BOINCDefs.SUSPEND_NOT_SUSPENDED)) { if((status.task_mode == BOINCDefs.RUN_MODE_AUTO) && (status.task_suspend_reason != BOINCDefs.SUSPEND_NOT_SUSPENDED)) {
computingStatus = COMPUTING_STATUS_SUSPENDED; computingStatus = COMPUTING_STATUS_SUSPENDED;
computingSuspendReason = status.task_suspend_reason; computingSuspendReason = status.task_suspend_reason;
computingParseError = false; computingParseError = false;
setWakeLock(false);
return; return;
} }
if((status.task_mode == BOINCDefs.RUN_MODE_AUTO) && (status.task_suspend_reason == BOINCDefs.SUSPEND_NOT_SUSPENDED)) { if((status.task_mode == BOINCDefs.RUN_MODE_AUTO) && (status.task_suspend_reason == BOINCDefs.SUSPEND_NOT_SUSPENDED)) {
@ -244,11 +278,13 @@ public class ClientStatus {
computingStatus = COMPUTING_STATUS_COMPUTING; computingStatus = COMPUTING_STATUS_COMPUTING;
computingSuspendReason = status.task_suspend_reason; // = 0 - SUSPEND_NOT_SUSPENDED computingSuspendReason = status.task_suspend_reason; // = 0 - SUSPEND_NOT_SUSPENDED
computingParseError = false; computingParseError = false;
setWakeLock(true);
return; return;
} else { // client "is able but idle" } else { // client "is able but idle"
computingStatus = COMPUTING_STATUS_IDLE; computingStatus = COMPUTING_STATUS_IDLE;
computingSuspendReason = status.task_suspend_reason; // = 0 - SUSPEND_NOT_SUSPENDED computingSuspendReason = status.task_suspend_reason; // = 0 - SUSPEND_NOT_SUSPENDED
computingParseError = false; computingParseError = false;
setWakeLock(false);
return; return;
} }
} }

View File

@ -56,7 +56,7 @@ import edu.berkeley.boinc.rpc.Transfer;
public class Monitor extends Service { public class Monitor extends Service {
private final String TAG = "BOINC Monitor Service"; private static final String TAG = "BOINC Monitor Service";
private static ClientStatus clientStatus; //holds the status of the client as determined by the Monitor private static ClientStatus clientStatus; //holds the status of the client as determined by the Monitor
private static AppPreferences appPrefs; //hold the status of the app, controlled by AppPreferences private static AppPreferences appPrefs; //hold the status of the app, controlled by AppPreferences
@ -428,7 +428,7 @@ public class Monitor extends Service {
public static ClientStatus getClientStatus() { //singleton pattern public static ClientStatus getClientStatus() { //singleton pattern
if (clientStatus == null) { if (clientStatus == null) {
clientStatus = new ClientStatus(); Log.d(TAG,"WARNING: clientStatus not yet initialized");
} }
return clientStatus; return clientStatus;
} }
@ -480,7 +480,7 @@ public class Monitor extends Service {
retryAttempts = getResources().getInteger(R.integer.monitor_setup_connection_retry_attempts); retryAttempts = getResources().getInteger(R.integer.monitor_setup_connection_retry_attempts);
// initialize singleton helper classes and provide application context // initialize singleton helper classes and provide application context
getClientStatus().setCtx(this); clientStatus = new ClientStatus(this);
getAppPrefs().readPrefs(this); getAppPrefs().readPrefs(this);
if(!started) { if(!started) {
@ -507,12 +507,14 @@ public class Monitor extends Service {
// //
monitorRunning = false; monitorRunning = false;
monitorThread.interrupt(); monitorThread.interrupt();
clientStatus.setWakeLock(false); // release wakeLock, if held.
// Quit client here is not appropriate?! // Quit client here is not appropriate?!
// Keep Client running until explecitely killed, independently from UI // Keep Client running until explecitely killed, independently from UI
//quitClient(); //quitClient();
//Toast.makeText(this, "BOINC Monitor Service Stopped", Toast.LENGTH_SHORT).show(); //android.widget.Toast.makeText(this, "BOINC Monitor Service Stopped", android.widget.Toast.LENGTH_SHORT).show();
} }
@Override @Override