diff options
-rw-r--r-- | AndroidManifest.xml | 8 | ||||
-rw-r--r-- | ReleaseNotes.txt | 204 | ||||
-rw-r--r-- | project.properties | 2 | ||||
-rw-r--r-- | src/com/dsi/ant/server/AntService.java | 221 | ||||
-rw-r--r-- | src/com/dsi/ant/server/StateChangedReceiver.java | 43 |
5 files changed, 436 insertions, 42 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 9336b82..28b95be 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -16,8 +16,8 @@ limitations under the License. --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.dsi.ant.server" - android:versionName="3.0.0" - android:versionCode="030000" + android:versionName="3.1.0" + android:versionCode="030100" android:sharedUserId="android.uid.system"> <uses-sdk @@ -49,7 +49,7 @@ limitations under the License. <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> - + </application> <!-- These permissions should be defined in the system --> @@ -71,5 +71,7 @@ limitations under the License. android:description="@string/permdesc_antradio" android:label="@string/permlab_antradio"/> + <uses-permission android:name="android.permission.BLUETOOTH" /> + <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> </manifest> diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt new file mode 100644 index 0000000..82df96b --- /dev/null +++ b/ReleaseNotes.txt @@ -0,0 +1,204 @@ +AntHalService - Release Notes +v3.1.0 +2013-07-19 + +Copyright 2011 Dynastream Innovations + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +============================================================= +1. USAGE + +The ANT HAL Service provides a transport from the ANT Radio Service (or +any application which binds to IAntHal AIDL) through JNI to the native ANT +stack code (libantradio.so). It provides the basics of send/recieve Rx +messages, enable, disable and get the enebaled state. + +============================================================= +2. REVISION HISTORY + +v3.1.0 : 2013-07-19 : Android_System_ANTHALService_3-1-0 + +Task + [ANTDROID-2035] - Remove tabs from AntService + [ANTDROID-1987] - Enable Bluetooth when ANT is enabled, if required by chip + +v3.0.0 : 2013-01-17 : Android_System_ANTHALService_3-0-0 + +Bug + + [ANTDROID-1383] - Can not build for Android 4.2 [Delete integration with BluetoothService] + [ANTDROID-1389] - onDestroy() starts new disable thread, when it should be ensuring there are no threads left running + +------------------------------------------------------------- + +v2.1.0 : 2012-07-20 : Android_System_ANTHALService_2-1-0 + +Bug + + [ANTDROID-992] - getEnabledState returns disabled while ANT is enabling in BT service + [ANTDROID-1007] - if enable is called, and already enabled, ENABLED then ENABLING is sent out + +Task + + [ANTDROID-1256] - Remove "DSI BlueZ" from name as service is generic + [ANTDROID-1248] - Remove full path from repository + [ANTDROID-1286] - Synchronise all updating of state + +------------------------------------------------------------- + +v2.0.0 : 2012-07-20 : Android_System_ANTHALService_2-0-0 + +Improvement + + * [ANTDROID-614] - Specify targetSdkVersion to let the system use compatibility behaviours for newer versions + +New Feature + + * [ANTDROID-953] - Do ANT enable/disable through BluetoothService ANT methods if they exist + +Task + + * [ANTDROID-938] - .classpath needs new entry for ADT Libraries + +Sub-task + + * [ANTDROID-786] - Only include LICENCE and NOTICE in system-package_X directories + +------------------------------------------------------------- + +v1.3.2 : 2012-04-02 : Android_System_ANTHALService_1-3-2 + +Bug + + [ANTDROID-570] - Unregister callback does not work correctly + +New Feature + + [ANTDROID-611] - Define meta-data to notify that this service provides a connection to built-in ANT hardware + +------------------------------------------------------------- + +v1.3.1 : 2012-03-20 : Android_System_ANTHALService_1-3-1 + +Bug + + [ANTDROID-533] - Document how to build in to Android with a single HOWTO for each platform type (not seperate steps per component) + +------------------------------------------------------------- + +v1.3.0 : 2012-02-22 : Android_System_AntHalService_1-3-0 + +Code Task + + * [ANTDROID-510] - Project has both proguard.cfg and proguard.flags files + +Improvement + + * [ANTDROID-511] - Create Hard Reset call from ARS to native + +New Feature + + * [ANTDROID-483] - configure ANT in Android build by chip + +Sub-task + + * [ANTDROID-481] - create callback for native code so it can do state change intents + + +------------------------------------------------------------- + +v1.2.0 : 2011-12-12 : Android_System_AntHalService_1-2-0 + +Bug + + * [ANTDROID-314] - An unsuccessful JAntJava.create() doesn't do anything + * [ANTDROID-380] - Change target API to 7 for onStartCommand() support + * [ANTDROID-382] - Service will not run for ever once restarted after being destroyed + * [ANTDROID-384] - Nullpointer in disable thread if onDestroy was called + +Code Task + + * [ANTDROID-126] - Ensure header/license is on all possibly released source files + * [ANTDROID-331] - Update/Sync up documentation of AIDL system service interface + * [ANTDROID-338] - Update projects for ADT r14 (naming and configuration) + +Improvement + + * [ANTDROID-222] - Each component adding to/modifying Android framework should include full path within Android source + +New Feature + + * [ANTDROID-7] - Check if "ant" is in Settings.System.AIRPLANE_MODE_RADIOS. + +Task + + * [ANTDROID-197] - Individual "how to include in build" file for each component, and Vendors Package HOW TO just says what the components are and where to find HOW TO for each + +------------------------------------------------------------- + +v1.1.0 : 2011-10-14 : Android_System_AntHalService_1-1-0 + +Bug + + * [ANTDROID-198] - "Commented out mutex on tx message to test lower level mutex" commit, but change still exists + * [ANTDROID-215] - Manifest does not point to correct location of BootCompletedReceiver class + +Improvement + + * [ANTDROID-170] - ANT HAL Service should start at BOOT_COMPLETED and run forever + * [ANTDROID-214] - Remove unnecessary Bluetooth and Vibrate permissions + * [ANTDROID-223] - Put enable and disable on their own threads + +Task + + * [ANTDROID-176] - Create ANT HAL Service Release Notes / Revision history / versioning + +------------------------------------------------------------- + +v1.0.0 : 2011-09-15 : Android_System_AntHalService_1-0-0 + +Bug + + * [ANTDROID-147] - Dead objects in AntService.java mCallbackList are not cleared + * [ANTDROID-149] - AntService and JAntJava are able to register multiple callback functions + +Improvement + + * [ANTDROID-232] - Use a single JAntJava instance across enable/disables + * [ANTDROID-233] - Get state (enabled, enabling,...) of ANT chip from lowest layer + * [ANTDROID-234] - ANT System Service as independent application (not a thread in system_process) + +Task + + * [ANTDROID-243] - Treat each component as independent from others (ie stack library, service, command line app, bluedroid rework) + +------------------------------------------------------------- + +Previous versions were not a stand-alone component. + +============================================================= +3. TODO + +ANTDROID-685 Update to follow Android Code Style guidelines +ANTDROID-383 Allow multiple clients to register IAntHalCallback +ANTDROID-346 Create AntHalLib +ANTDROID-309 What is Version.java used for for AntHal? +ANTDROID-246 Store platform specific values in system settings +ANTDROID-244 Separate data and command paths + +============================================================= +4. KNOWN ISSUES + +ANTDROID-961 On a phone with no BluetoothService, ANT HAL will not work +ANTDROID-615 When debugging, registerCallback() doesn't check if callback is null before logging value diff --git a/project.properties b/project.properties index 5a70945..c4f09d2 100644 --- a/project.properties +++ b/project.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=android-7 +target=android-17 diff --git a/src/com/dsi/ant/server/AntService.java b/src/com/dsi/ant/server/AntService.java index 1619c0b..1ed828f 100644 --- a/src/com/dsi/ant/server/AntService.java +++ b/src/com/dsi/ant/server/AntService.java @@ -18,12 +18,18 @@ package com.dsi.ant.server; +import android.bluetooth.BluetoothAdapter; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.app.Service; +import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; +import android.provider.Settings; import android.util.Log; +import android.os.SystemProperties; import com.dsi.ant.core.*; @@ -40,15 +46,94 @@ public class AntService extends Service public static final String ANT_SERVICE = "AntService"; + /** + * Allows the application to directly configure the ANT radio through the + * proxy service. Malicious applications may prevent other ANT applications + * from connecting to ANT devices + */ + public static final String ANT_ADMIN_PERMISSION = "com.dsi.ant.permission.ANT_ADMIN"; + + /** + * Request that ANT be enabled + */ + public static final String ACTION_REQUEST_ENABLE = "com.dsi.ant.server.action.REQUEST_ENABLE"; + + /** + * Request that ANT be disabled + */ + public static final String ACTION_REQUEST_DISABLE = "com.dsi.ant.server.action.REQUEST_DISABLE"; + private JAntJava mJAnt = null; private boolean mInitialized = false; + /** + * Flag for if Bluetooth needs to be enabled for ANT to enable + */ + private boolean mRequiresBluetoothOn = false; + + /** + * Flag which specifies if we are waiting for an ANT enable intent + */ + private boolean mEnablePending = false; + private Object mChangeAntPowerState_LOCK = new Object(); private static Object sAntHalServiceDestroy_LOCK = new Object(); IAntHalCallback mCallback; + /** + * Receives Bluetooth State Changed intent and sends {@link ACTION_REQUEST_ENABLE} + * and {@link ACTION_REQUEST_DISABLE} accordingly + */ + private final StateChangedReceiver mStateChangedReceiver = new StateChangedReceiver(); + + /** + * Receives {@link ACTION_REQUEST_ENABLE} and {@link ACTION_REQUEST_DISABLE} + * intents to enable and disable ANT. + */ + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (mRequiresBluetoothOn) { + String action = intent.getAction(); + if (ACTION_REQUEST_ENABLE.equals(action)) { + if (mEnablePending) { + asyncSetAntPowerState(true); + mEnablePending = false; + } + } else if (ACTION_REQUEST_DISABLE.equals(action)) { + if (mEnablePending) { + mEnablePending = false; + } else { + asyncSetAntPowerState(false); + } + } + } + } + }; + + /** + * Checks if Bluetooth needs to be turned on for ANT to enable + */ + private boolean requiresBluetoothOn() { + return isQcomPlatform(); + } + + /** + * Checks if the current platform is QCom + */ + private boolean isQcomPlatform() + { + if ((SystemProperties.get("ro.board.platform").equals("msm8974")) + || (SystemProperties.get("ro.board.platform").equals("msm8610")) + || (SystemProperties.get("ro.board.platform").equals("msm8226"))) { + + return true; + } + return false; + } + public static boolean startService(Context context) { return ( null != context.startService(new Intent(IAntHal.class.getName())) ); @@ -99,7 +184,45 @@ public class AntService extends Service { case AntHalDefine.ANT_HAL_STATE_ENABLED: { - result = asyncSetAntPowerState(true); + result = AntHalDefine.ANT_HAL_RESULT_FAIL_NOT_ENABLED; + + boolean waitForBluetoothToEnable = false; + + if (mRequiresBluetoothOn) { + + // Try to turn on BT if it is not enabled. + BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + + if (bluetoothAdapter != null) { + + // run with permissions of ANTHALService + long callingPid = Binder.clearCallingIdentity(); + + if (!bluetoothAdapter.isEnabled()) { + + waitForBluetoothToEnable = true; + mEnablePending = true; + + boolean isEnabling = bluetoothAdapter.enable(); + + // if enabling adapter has begun, return + // success. + if (isEnabling) { + result = AntHalDefine.ANT_HAL_RESULT_SUCCESS; + // StateChangedReceiver will receive + // enabled status and then enable ANT + } else { + mEnablePending = false; + } + } + + Binder.restoreCallingIdentity(callingPid); + } + } + + if (!waitForBluetoothToEnable) { + result = asyncSetAntPowerState(true); + } break; } case AntHalDefine.ANT_HAL_STATE_DISABLED: @@ -143,44 +266,48 @@ public class AntService extends Service */ private int asyncSetAntPowerState(final boolean state) { - int result = AntHalDefine.ANT_HAL_RESULT_FAIL_UNKNOWN; - - synchronized(mChangeAntPowerState_LOCK) { - // Check we are not already in/transitioning to the state we want - int currentState = doGetAntState(); - - if(state) { - if((AntHalDefine.ANT_HAL_STATE_ENABLED == currentState) - || (AntHalDefine.ANT_HAL_STATE_ENABLING == currentState)) { - if(DEBUG) Log.d(TAG, "Enable request ignored as already enabled/enabling"); - - return AntHalDefine.ANT_HAL_RESULT_SUCCESS; - } else if(AntHalDefine.ANT_HAL_STATE_DISABLING == currentState) { - Log.w(TAG, "Enable request ignored as already disabling"); - - return AntHalDefine.ANT_HAL_RESULT_FAIL_UNKNOWN; - } - } else { - if((AntHalDefine.ANT_HAL_STATE_DISABLED == currentState) - || (AntHalDefine.ANT_HAL_STATE_DISABLING == currentState)) { - if(DEBUG)Log.d(TAG, "Disable request ignored as already disabled/disabling"); - - return AntHalDefine.ANT_HAL_RESULT_SUCCESS; - } else if(AntHalDefine.ANT_HAL_STATE_ENABLING == currentState) { - Log.w(TAG, "Disable request ignored as already enabling"); - - return AntHalDefine.ANT_HAL_RESULT_FAIL_UNKNOWN; - } - } - - if (state) { - result = enableBackground(); - } else { - result = disableBackground(); - } + int result = AntHalDefine.ANT_HAL_RESULT_FAIL_UNKNOWN; + + synchronized (mChangeAntPowerState_LOCK) { + // Check we are not already in/transitioning to the state we want + int currentState = doGetAntState(); + + if (state) { + if ((AntHalDefine.ANT_HAL_STATE_ENABLED == currentState) + || (AntHalDefine.ANT_HAL_STATE_ENABLING == currentState)) { + if (DEBUG) { + Log.d(TAG, "Enable request ignored as already enabled/enabling"); + } + + return AntHalDefine.ANT_HAL_RESULT_SUCCESS; + } else if (AntHalDefine.ANT_HAL_STATE_DISABLING == currentState) { + Log.w(TAG, "Enable request ignored as already disabling"); + + return AntHalDefine.ANT_HAL_RESULT_FAIL_UNKNOWN; + } + } else { + if ((AntHalDefine.ANT_HAL_STATE_DISABLED == currentState) + || (AntHalDefine.ANT_HAL_STATE_DISABLING == currentState)) { + if (DEBUG) { + Log.d(TAG, "Disable request ignored as already disabled/disabling"); + } + + return AntHalDefine.ANT_HAL_RESULT_SUCCESS; + } else if (AntHalDefine.ANT_HAL_STATE_ENABLING == currentState) { + Log.w(TAG, "Disable request ignored as already enabling"); + + return AntHalDefine.ANT_HAL_RESULT_FAIL_UNKNOWN; + } + } + + if (state) { + result = enableBackground(); + } else { + result = disableBackground(); + } } - - return result; + + return result; } /** @@ -430,6 +557,7 @@ public class AntService extends Service } // create a single new JAnt HCI Interface instance mJAnt = new JAntJava(); + mRequiresBluetoothOn = requiresBluetoothOn(); JAntStatus createResult = mJAnt.create(mJAntCallback); if (createResult == JAntStatus.SUCCESS) @@ -444,6 +572,17 @@ public class AntService extends Service if (DEBUG) Log.e(TAG, "JAntJava create failed: " + createResult); } + + IntentFilter filter = new IntentFilter(); + filter.addAction(ACTION_REQUEST_ENABLE); + filter.addAction(ACTION_REQUEST_DISABLE); + registerReceiver(mReceiver, filter); + + if (mRequiresBluetoothOn) { + IntentFilter stateChangedFilter = new IntentFilter(); + stateChangedFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); + registerReceiver(mStateChangedReceiver, stateChangedFilter); + } } @Override @@ -471,6 +610,12 @@ public class AntService extends Service { super.onDestroy(); } + + if (mRequiresBluetoothOn) { + unregisterReceiver(mStateChangedReceiver); + } + + unregisterReceiver(mReceiver); } @Override diff --git a/src/com/dsi/ant/server/StateChangedReceiver.java b/src/com/dsi/ant/server/StateChangedReceiver.java new file mode 100644 index 0000000..4479003 --- /dev/null +++ b/src/com/dsi/ant/server/StateChangedReceiver.java @@ -0,0 +1,43 @@ +/* + Copyright 2013 Dynastream Innovations + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package com.dsi.ant.server; + +import android.bluetooth.BluetoothAdapter; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +public class StateChangedReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + // Bluetooth State Changed + if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) { + + int bluetoothState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0); + + if (BluetoothAdapter.STATE_OFF == bluetoothState) { + Intent antIntent = new Intent(AntService.ACTION_REQUEST_DISABLE); + context.sendBroadcast(antIntent, AntService.ANT_ADMIN_PERMISSION); + } else if (BluetoothAdapter.STATE_ON == bluetoothState) { + Intent antIntent = new Intent(AntService.ACTION_REQUEST_ENABLE); + context.sendBroadcast(antIntent, AntService.ANT_ADMIN_PERMISSION); + } + } // else if <<Another device dependency>> state change + + } +} |