summaryrefslogtreecommitdiffstats
path: root/wipower-host
diff options
context:
space:
mode:
authorKiran Kelageri <kirankelageri@codeaurora.org>2015-07-30 16:16:14 -0700
committerKiran Kelageri <kirankelageri@codeaurora.org>2015-08-04 14:42:58 -0700
commitfbec7160bd960dc9a98c2b924554710d3f77a411 (patch)
tree00e1efe941a0dbddb9206a60b39830f636e2873a /wipower-host
parent675d87c33ad8008f93b2f83b2db13a981a1321e7 (diff)
downloadandroid_packages_apps_BluetoothExt-fbec7160bd960dc9a98c2b924554710d3f77a411.tar.gz
android_packages_apps_BluetoothExt-fbec7160bd960dc9a98c2b924554710d3f77a411.tar.bz2
android_packages_apps_BluetoothExt-fbec7160bd960dc9a98c2b924554710d3f77a411.zip
Bluetooth-Wipower: Wipower refactoring.
Wipower code move from aosp (packages and frameworks) to vendor on M. Change-Id: I632d456acc99f53c482c828a9b44b2bea8a7d7fb
Diffstat (limited to 'wipower-host')
-rw-r--r--wipower-host/Android.mk5
-rw-r--r--wipower-host/a4wp/Android.mk25
-rw-r--r--wipower-host/a4wp/AndroidManifest.xml85
-rw-r--r--wipower-host/a4wp/src/org/codeaurora/bluetooth/a4wp_app/A4wpService.java1131
-rw-r--r--wipower-host/a4wp/src/org/codeaurora/bluetooth/a4wp_app/BTEventHandler.java78
-rw-r--r--wipower-host/a4wp/src/org/codeaurora/bluetooth/wipower/BTEventHandler.java79
-rw-r--r--wipower-host/a4wp/src/org/codeaurora/bluetooth/wipower/WipowerApp.java47
-rw-r--r--wipower-host/a4wp/src/org/codeaurora/bluetooth/wipower/WipowerService.java371
-rw-r--r--wipower-host/jni/Android.mk30
-rw-r--r--wipower-host/jni/android_hardware_wipower.cpp425
-rw-r--r--wipower-host/jni/android_hardware_wipower.h47
-rw-r--r--wipower-host/wipower_lib/Android.mk19
-rw-r--r--wipower-host/wipower_lib/android.wipower.xml34
-rw-r--r--wipower-host/wipower_lib/android/wipower/IWipower.aidl58
-rw-r--r--wipower-host/wipower_lib/android/wipower/IWipowerManagerCallback.aidl45
-rw-r--r--wipower-host/wipower_lib/android/wipower/WipowerDynamicParam.java213
-rw-r--r--wipower-host/wipower_lib/android/wipower/WipowerManager.java512
-rw-r--r--wipower-host/wipower_lib/android/wipower/WipowerManagerCallback.java89
18 files changed, 3293 insertions, 0 deletions
diff --git a/wipower-host/Android.mk b/wipower-host/Android.mk
new file mode 100644
index 0000000..20d13f5
--- /dev/null
+++ b/wipower-host/Android.mk
@@ -0,0 +1,5 @@
+ifeq ($(BOARD_USES_WIPOWER),true)
+LOCAL_PATH := $(call my-dir)
+include $(call all-subdir-makefiles)
+endif
+
diff --git a/wipower-host/a4wp/Android.mk b/wipower-host/a4wp/Android.mk
new file mode 100644
index 0000000..996d243
--- /dev/null
+++ b/wipower-host/a4wp/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+src_dirs:= src/org/codeaurora/bluetooth/a4wp_app \
+ src/org/codeaurora/bluetooth/wipower
+
+LOCAL_SRC_FILES := \
+ $(call all-java-files-under, $(src_dirs))
+
+LOCAL_PACKAGE_NAME := a4wpservice
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES += com.quicinc.wbc
+LOCAL_JAVA_LIBRARIES += android.wipower
+
+LOCAL_REQUIRED_MODULES := bluetooth.default
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+LOCAL_MULTILIB := 32
+LOCAL_JNI_SHARED_LIBRARIES := libwipower_jni
+
+include $(BUILD_PACKAGE)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/wipower-host/a4wp/AndroidManifest.xml b/wipower-host/a4wp/AndroidManifest.xml
new file mode 100644
index 0000000..ef75a6f
--- /dev/null
+++ b/wipower-host/a4wp/AndroidManifest.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.codeaurora.bt_wipower"
+ android:sharedUserId="android.uid.bluetooth">
+
+ <original-package android:name="org.codeaurora.bt_wipower" />
+
+ <uses-permission android:name="android.permission.ACCESS_BLUETOOTH_SHARE" />
+ <uses-permission android:name="android.permission.BLUETOOTH" />
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+ <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.BLUETOOTH_STACK" />
+ <application android:process="com.android.bluetooth"
+ android:name=".wipower.WipowerApp"
+ android:persistent="false"
+ android:supportsRtl="true">
+ <uses-library android:name="com.quicinc.wbc"
+ android:required="false" />
+ <uses-library android:name="android.wipower"
+ android:required="false" />
+ <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
+ <receiver
+ android:name=".wipower.BTEventHandler"
+ android:exported="true"
+ android:enabled="true"
+ android:process="com.android.bluetooth">
+ <intent-filter>
+ <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
+ </intent-filter>
+ </receiver>
+ <service
+ android:name = ".wipower.WipowerService"
+ android:exported="true"
+ android:enabled="true"
+ android:process="com.android.bluetooth">
+ <intent-filter>
+ <action android:name="android.wipower.IWipower" />
+ </intent-filter>
+ </service>
+
+ <service
+ android:process="com.android.bluetooth"
+ android:exported="true"
+ android:name = ".a4wp.A4wpService">
+ </service>
+ <receiver
+ android:process="com.android.bluetooth"
+ android:exported="true"
+ android:name=".a4wp.BTEventHandler">
+ <intent-filter>
+ <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
+ </intent-filter>
+ </receiver>
+
+ </application>
+</manifest>
diff --git a/wipower-host/a4wp/src/org/codeaurora/bluetooth/a4wp_app/A4wpService.java b/wipower-host/a4wp/src/org/codeaurora/bluetooth/a4wp_app/A4wpService.java
new file mode 100644
index 0000000..c5024a6
--- /dev/null
+++ b/wipower-host/a4wp/src/org/codeaurora/bluetooth/a4wp_app/A4wpService.java
@@ -0,0 +1,1131 @@
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bt_wipower.a4wp;
+
+import java.util.UUID;
+
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCallback;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattDescriptor;
+import android.bluetooth.BluetoothGattService;
+import android.bluetooth.BluetoothGattServer;
+import android.bluetooth.BluetoothGattServerCallback;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.app.Service;
+import android.net.Credentials;
+import java.io.OutputStream;
+import android.util.Log;
+import android.os.IBinder;
+import android.content.Intent;
+import android.os.Process;
+import java.nio.ByteBuffer;
+import android.wipower.WipowerManager;
+import android.wipower.WipowerManagerCallback;
+import android.wipower.WipowerManager.WipowerState;
+import android.wipower.WipowerManager.PowerApplyEvent;
+import android.wipower.WipowerManager.PowerLevel;
+import android.wipower.WipowerDynamicParam;
+import com.quicinc.wbc.WbcManager;
+import com.quicinc.wbc.WbcTypes;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+
+import android.bluetooth.le.AdvertiseCallback;
+import android.bluetooth.le.AdvertiseSettings;
+import android.bluetooth.le.AdvertiseData;
+import android.bluetooth.le.BluetoothLeAdvertiser;
+import android.os.ParcelUuid;
+import android.os.PowerManager;
+import android.os.SystemProperties;
+
+/**
+ * Class which executes A4WP service
+ */
+public class A4wpService extends Service
+{
+ private static final String LOGTAG = "A4wpService";
+ private static OutputStream mOutputStream = null;
+ private BluetoothAdapter mBluetoothAdapter = null;
+ private BluetoothGattServer mBluetoothGattServer = null;
+ private BluetoothGattCharacteristic mPruAlertChar = null;
+ private BluetoothDevice mDevice = null;
+ private PowerManager.WakeLock mWakeLock = null;
+
+ // Advertising variables
+ private final static int START_ADVERTISING = 1;
+ private final static int STOP_ADVERTISING = 0;
+
+ private static final UUID A4WP_SERVICE_UUID = UUID.fromString("6455fffe-a146-11e2-9e96-0800200c9a67");
+ //PRU writes
+ private static final UUID A4WP_PRU_CTRL_UUID = UUID.fromString("6455e670-a146-11e2-9e96-0800200c9a67");
+ private static final UUID A4WP_PTU_STATIC_UUID = UUID.fromString("6455e671-a146-11e2-9e96-0800200c9a67");
+ //PRU reads
+ private static final UUID A4WP_PRU_ALERT_UUID = UUID.fromString("6455e672-a146-11e2-9e96-0800200c9a67");
+ private static final UUID A4WP_PRU_STATIC_UUID = UUID.fromString("6455e673-a146-11e2-9e96-0800200c9a67");
+ private static final UUID A4WP_PRU_DYNAMIC_UUID = UUID.fromString("6455e674-a146-11e2-9e96-0800200c9a67");
+
+ private static final UUID A4WP_PRU_ALERT_DESC_UUID = UUID.fromString("64552902-a146-11e2-9e96-0800200c9a67");
+
+ private static final Object mLock = new Object();
+ private int mState = BluetoothProfile.STATE_DISCONNECTED;
+
+ private final static short DEFAULT_FIELDS = 0x0000;
+ private final static short DEFAULT_PROTOCOL_REV = 0x0000;
+ private final static short DEFAULT_RFU = 0x0000;
+ //03 if MTP, Has to be 04 for fluid.
+ private final static byte DEFAULT_CATEGORY = 0x0003;
+ private final static byte DEFAULT_CAPABILITIES = 0x0010;
+ private final static byte DEFAULT_HW_VERSION = 0x0007;
+ private final static byte DEFAULT_FW_VERSION = 0x0006;
+ private final static byte DEFAULT_MAX_POWER_DESIRED = 0x0032; // 5Watts
+ private final static short DEFAULT_VRECT_MIN = 7100; // 7.1 Volts
+ private final static short DEFAULT_VRECT_MAX = 19300; // 19.3 Volts
+ private final static short DEFAULT_VRECT_SET = 7100; // 7.1 Volts
+ private final static short DEFAULT_DELTA_R1 = 0x0001;
+ private final static int DEFAULT_RFU_VAL = 0x0000;
+ private static final int MSB_MASK = 0xFF00;
+ private static final int LSB_MASK= 0x00FF;
+ // On charge port disbaled need to be set to 10.2 Volts
+ private final static short VRECT_MIN_CHG_DISABLED = 10200;
+ // Populate Vrectmin, Vrectmax, Vrectset and temperature in the optional fields
+ private final static byte OPTIONAL_FIELD_MASK = 0x3C;
+
+ //Timeout value set to 5Sec which enures we advertise in limited mode
+ private static final int WIPOWER_ADV_TIMEOUT = 5000;
+
+ //PRU Write param length for validation
+ private static final byte A4WP_PTU_STATIC_LENGTH = 0x11;
+ private static final byte A4WP_PRU_CTRL_LENGTH = 0x05;
+ private static final byte CCCD_LENGTH = 0x02; // Client Characteristic Configuration Declaration length
+
+ //Advertisement interval values.
+ private static final byte A4WP_ADV_MIN_INTERVAL = 0x20;
+ private static final byte A4WP_ADV_MAX_INTERVAL = 0x20;
+
+ //mask bits for charge port and irect validations
+ private static final int CHARGE_PORT_MASK = 0x02;
+ private static final int IRECT_MASK_MSB = 0x00;
+ private static final int IRECT_MASK_LSB = 0x15;
+ private static final int VRECT_MASK = 0x00;
+ private static short VRECT_DYN;
+
+ //Indices definitions
+ private static final int OPTIONAL_FIELDS = 0;
+ private static final int VRECT_LSB = 1;
+ private static final int VRECT_MSB = 2;
+ private static final int IRECT_LSB = 3;
+ private static final int IRECT_MSB = 4;
+ private static final int VRECT_MIN_LSB = 10;
+ private static final int VRECT_MIN_MSB = 11;
+ private static final int VRECT_SET_LSB = 12;
+ private static final int VRECT_SET_MSB = 13;
+ private static final int VRECT_MAX_LSB = 14;
+ private static final int VRECT_MAX_MSB = 15;
+ private static final int PRU_ALERT = 16;
+
+ private static boolean mWipowerBoot = false;
+ private static boolean isChargePortSet = false;
+ static boolean mChargeComplete = true;
+ static boolean mOutputControl = false;
+ private static boolean mDiscInitiated = false; // If TRUE, means A4WP app has initiated the disconnection with PTU
+ private static boolean mEnablePruAlerts = false; // Are PRU Alerts enabled
+
+ private AdvertiseSettings mAdvertiseSettings;
+ private AdvertiseData mAdvertisementData;
+ private BluetoothLeAdvertiser mAdvertiser;
+ private AdvertiseCallback mAdvertiseCallback = new myAdvertiseCallback(1);
+ ParcelUuid uuid1 = ParcelUuid.fromString("6455fffe-a146-11e2-9e96-0800200c9a67");
+
+ /*a> Due to bad coupling irect value drops to zero and vrect remains
+ constant would render stark to reset the CHG_OK pin, So as to
+ set this pin on coupling being recovered host delivers the charge
+ enable command to set the CHG_OK pin.
+ b> Charge port needs to be enabled only if the vrect value is greater
+ than the Vmin values */
+ private void chkDynParamsAndStartCharging(byte[] value)
+ {
+ VRECT_DYN = 0x00;
+ if (!isChargePortSet) {
+ VRECT_DYN = (short)toUnsigned(value[VRECT_LSB]);
+ VRECT_DYN |= (short)(toUnsigned(value[VRECT_MSB]) << 8);
+ if (DEFAULT_VRECT_MIN <= VRECT_DYN && mOutputControl) {
+ mWipowerManager.startCharging();
+ isChargePortSet = true;
+ }
+ }
+ if (isChargePortSet) {
+ if ((byte)(value[PRU_ALERT] & CHARGE_PORT_MASK) == CHARGE_PORT_MASK) {
+ if ((value[IRECT_LSB] <= IRECT_MASK_LSB && value[IRECT_MSB] == IRECT_MASK_MSB)
+ && (value[VRECT_LSB] > VRECT_MASK || value[VRECT_MSB] > VRECT_MASK)) {
+ mWipowerManager.startCharging();
+ }
+ }
+ }
+ }
+
+ private synchronized void initiateDisconnection() {
+ Log.v(LOGTAG, "initiateDisconnection:" + " mDiscInitiated:" + mDiscInitiated + " mState:" + mState);
+ if ((mDiscInitiated == false) && (mState == BluetoothProfile.STATE_CONNECTED))
+ {
+ if (mBluetoothGattServer != null && mDevice != null) {
+ Log.v(LOGTAG, "initiateDisconnection:" + " dropping Connection");
+ mDiscInitiated = true;
+ mBluetoothGattServer.cancelConnection(mDevice);
+ if (mChargeComplete == true) {
+ mWipowerManager.enablePowerApply(true, true, true);
+ } else {
+ mWipowerManager.enablePowerApply(true, true, false);
+ }
+ }
+ }
+ return;
+ }
+
+ private WbcManager.WbcEventListener mWbcCallback = new WbcManager.WbcEventListener() {
+
+ @Override
+ public void onWbcEventUpdate(int what, int arg1, int arg2) {
+ Log.v(LOGTAG, "onWbcEventUpdate rcvd: " + what + ", " + arg1 + ", " + arg2);
+ if ((what == WbcTypes.WBC_EVENT_TYPE_CHARGING_REQUIRED_STATUS)){
+ if ((arg1 == WbcTypes.WBC_BATTERY_STATUS_CHARGING_NOT_REQUIRED)){
+ // this will set charge complete bit in pru alert
+ // eventally leading to a possible disconnect from ptu
+ mChargeComplete = true;
+ if (mPruAlert != null)
+ {
+ byte alert = 0;
+ alert = (byte) (alert | CHARGE_COMPLETE_BIT);
+ mPruAlert.sendPruAlert(alert);
+ }
+ } else {
+ // We could be in 600mS scan state here and since charging needs to be resumed
+ // send enable power apply command to scan for short beacons */
+ mChargeComplete = false;
+ if ((mState == BluetoothProfile.STATE_DISCONNECTED) && (mWipowerManager != null))
+ mWipowerManager.enablePowerApply(true, true, false);
+ }
+ } else if (what == WbcTypes.WBC_EVENT_TYPE_PTU_PRESENCE_STATUS) {
+ if (arg1 == WbcTypes.WBC_PTU_STATUS_NOT_PRESENT) {
+ initiateDisconnection();
+ }
+ }
+ Log.v(LOGTAG, "onWbcEventUpdate: charge complete " + mChargeComplete);
+ }
+ };
+
+ private void acquire_wake_lock(boolean wake) {
+ if (wake == true) {
+ if (mWakeLock == null) {
+ PowerManager pm = (PowerManager)getSystemService(
+ Context.POWER_SERVICE);
+ if (pm == null) {
+ Log.e(LOGTAG, "failed to get PM");
+ return;
+ }
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+ "StartingWipowerConnection");
+ mWakeLock.setReferenceCounted(false);
+ mWakeLock.acquire();
+ Log.w(LOGTAG, "Acquire Wake Lock");
+ } else {
+ Log.w(LOGTAG, "Wake Lock already held");
+ }
+ } else {
+ if (mWakeLock != null) {
+ mWakeLock.release();
+ mWakeLock = null;
+ Log.w(LOGTAG, "Release Wake Lock");
+ }
+ }
+ }
+
+ private class PruStaticParam {
+ private byte mOptvalidity;
+ private byte mProtoRevision;
+ private byte mRfu;
+ private byte mCategory;
+ private byte mCapabilities;
+ private byte mHwRev;
+ private byte mFwRev;
+ private byte mMaxPowerDesired;
+ private short mVrectMinStatic;
+ private short mVrectMaxStatic;
+ private short mVrectSet;
+ private short mDeltaR1;
+ private int mRfuVal;
+
+ public PruStaticParam() {
+ mOptvalidity = (byte)DEFAULT_FIELDS;
+ mProtoRevision = (byte)DEFAULT_PROTOCOL_REV;
+ mRfu = (byte)DEFAULT_RFU;
+ mCategory = (byte)DEFAULT_CATEGORY;
+ mCapabilities = (byte)DEFAULT_CAPABILITIES;
+ mHwRev = (byte)DEFAULT_HW_VERSION;
+ mFwRev = (byte)DEFAULT_FW_VERSION;
+ mMaxPowerDesired = (byte)DEFAULT_MAX_POWER_DESIRED;
+ mVrectMinStatic = (short)DEFAULT_VRECT_MIN;
+ mVrectMaxStatic = (short)DEFAULT_VRECT_MAX;
+ mVrectSet = (short)DEFAULT_VRECT_SET;
+ mDeltaR1 = (short)DEFAULT_DELTA_R1;
+ mRfuVal = (int)DEFAULT_RFU_VAL;
+ Log.v(LOGTAG, "PruStaticParam initialized");
+ }
+
+ public byte[] getValue() {
+ byte[] res = new byte[20];
+ res[0] = mOptvalidity;
+ res[1] = mProtoRevision;
+ res[2] = mRfu;
+ res[3] = mCategory;
+ res[4] = mCapabilities;
+ res[5] = mHwRev;
+ res[6] = mFwRev;
+ res[7] = mMaxPowerDesired;
+ res[8] = (byte)(LSB_MASK & mVrectMinStatic);
+ res[9] = (byte)((MSB_MASK & mVrectMinStatic) >> 8);
+ res[10] = (byte)(LSB_MASK & mVrectMaxStatic);
+ res[11] = (byte)((MSB_MASK & mVrectMaxStatic) >> 8);
+ res[12] = (byte)(LSB_MASK & mVrectSet);
+ res[13] = (byte)((MSB_MASK & mVrectSet) >> 8);
+ res[14] = (byte)(LSB_MASK & mDeltaR1);
+ res[15] = (byte)((MSB_MASK & mDeltaR1) >> 8);
+ res[16] = (byte)(LSB_MASK & mRfuVal);
+ res[17] = (byte)((MSB_MASK & mRfuVal) >> 8);
+ res[18] = (byte)((0xFF0000 & mRfuVal) >> 16);
+ res[19] = (byte)((0xFF000000 & mRfuVal) >> 24);
+
+ return res;
+ }
+
+ /*This is used to set the charging values*/
+ public void setValue(byte[] value) {
+ mOptvalidity = value[0];
+ mProtoRevision = value[1];
+ mRfu = value[2];
+ mCategory = value[3] ;
+ mCapabilities = value[4];
+ mHwRev = value[5];
+ mFwRev = value[6];
+ mMaxPowerDesired = value[7];
+ mVrectMinStatic = value[8];
+ mVrectMinStatic |= (short)(value[9] << 8);
+ mVrectMinStatic = value[10];
+ mVrectMinStatic |= (short)(value[11] << 8);
+ mVrectSet = value[12];
+ mVrectSet |= (short)(value[13] << 8);
+ mDeltaR1 = value[14];
+ mDeltaR1 |= (short)(value[15] << 8);
+ mRfuVal = value[16];
+ mRfuVal |= (int)(value[17] << 8);
+ mRfuVal |= (int)(value[18] << 16);
+ mRfuVal |= (int)(value[19] << 24);
+
+ return;
+ }
+
+ }
+
+ private class PruAlert {
+ private final int PRU_ALERT_NOTIFY_BIT = 0x0100; // Notify bit in CCCD
+ private byte mAlert;
+
+ public PruAlert(byte value) {
+ mAlert = value;
+ mEnablePruAlerts = false;
+ }
+
+ public void setValue(byte value) {
+ mAlert = value;
+ }
+
+ public byte[] getValue() {
+ byte[] res = new byte[1];
+ res[0] = mAlert;
+ return res;
+ }
+
+ // Handle the CCCD Write for Notifications/Indications from PTU
+ private int processPruAlertRequest(byte[] value) {
+ int status = 0;
+ int intValue= 0;
+ intValue = ((value[0]<< 8) & 0x0000ff00) | ((value[1] << 0) & 0x000000ff);
+
+ Log.v(LOGTAG, "processPruAlertRequest. Value: " + intValue);
+
+ if ((intValue & PRU_ALERT_NOTIFY_BIT) == PRU_ALERT_NOTIFY_BIT) {
+ Log.v(LOGTAG, "processPruAlertRequest. PRU Alerts Enabled");
+ mEnablePruAlerts = true;
+ mWipowerManager.enableAlertNotification(true);
+ } else {
+ mWipowerManager.enableAlertNotification(false);
+ mEnablePruAlerts = false;
+ }
+
+ return status;
+ } // end of processPruAlertRequest
+
+ // Send Notification/Indications to PTU
+ private int sendPruAlert(byte alertValue) {
+ int status = 0;
+ byte[] alertVal = {0};
+
+ Log.v(LOGTAG, "sendPruAlert. Value: " + alertValue);
+
+ if (mEnablePruAlerts == false)
+ {
+ Log.v(LOGTAG, "sendPruAlert. PRU Alerts are Disabled");
+ return status;
+ }
+
+ if (mPruAlertChar == null)
+ {
+ Log.v(LOGTAG, "sendPruAlert. Alert characteristic is NULL");
+ return status;
+ }
+
+ if (alertValue == 0)
+ {
+ Log.v(LOGTAG, "sendPruAlert. No alerts to send");
+ return status;
+ }
+
+ if (mDevice == null)
+ {
+ Log.v(LOGTAG, "sendPruAlert. mDevice is NULL");
+ return status;
+ }
+
+ if (mState != BluetoothProfile.STATE_CONNECTED)
+ {
+ Log.v(LOGTAG, "sendPruAlert. Not CONNECTED");
+ return status;
+ }
+
+
+ alertVal[0] = alertValue;
+ mPruAlertChar.setValue(alertVal);
+ mBluetoothGattServer.notifyCharacteristicChanged(mDevice,
+ mPruAlertChar, false);
+
+ return status;
+ } // end of sendPruAlert
+
+ }
+
+ private class PtuStaticParam {
+ private byte mOptValidity;
+ private byte mPower;
+ private byte mMaxSrcImpedence;
+ private byte mMaxLoadResistance;
+ private short mId;
+ private byte mClass;
+ private byte mHwRev;
+ private byte mFwRev;
+ private byte mProtocolRev;
+ private byte mMaxDevicesSupported;
+ private int mReserved1;
+ private short mReserved2;
+
+ public PtuStaticParam(byte[] value) {
+ mOptValidity = value[0];
+ mPower = value[1];
+ mMaxSrcImpedence = value[2];
+ mMaxLoadResistance = value[3];
+ mId = (short)(value[4] & 0xff);
+ mId |= (short)((value[5] & 0xff) << 8);
+ mClass = value[6];
+ mHwRev = value[7];
+ mFwRev = value[8];
+ mProtocolRev = value[9];
+ mMaxDevicesSupported = value[10];
+ mReserved1 = (int)(value[11] & 0xff);
+ mReserved1 |= (int)((value[12] & 0xff) << 8);
+ mReserved1 |= (int)((value[13] & 0xff) << 16);
+ mReserved1 |= (int)((value[14] & 0xff) << 16);
+ mReserved2 = (short)(value[15] & 0xff);
+ mReserved2 |= (short)((value[16] & 0xff) << 8);
+ }
+
+ public void print() {
+ Log.v(LOGTAG, "mOptValidity" + toHex(mOptValidity) + "mPower" + toHex(mPower) + "mMaxSrcImpedence" + toHex(mMaxSrcImpedence) + "mMaxLoadResistance" + toHex(mMaxLoadResistance));
+ Log.v(LOGTAG, "mId" + toHex(mId) + "mClass" + toHex(mClass) + "mHwRev" + toHex(mHwRev) + "mFwRev" + toHex(mFwRev));
+ Log.v(LOGTAG, "mProtocolRev" + toHex(mProtocolRev) + "mMaxDevicesSupported" + toHex(mMaxDevicesSupported) + "mReserved1" + toHex(mReserved1) + "mReserved2" + toHex(mReserved2));
+ }
+
+ public double getPower() {
+ double val = ((mPower&0xfc)>>2);
+ val = 0.5*(val+1);
+ Log.v(LOGTAG, "getPower<=" + val);
+ if (val > 22) val = 22.0;
+ return val;
+ }
+
+ public double getMaxSrcImpedence() {
+ double val = ((mMaxSrcImpedence&0xf8)>>3);
+ val = 50 + (val*10);
+ Log.v(LOGTAG, "getSrcImpedence<=" + val);
+ if (val > 375) val = 375.0;
+ return val;
+ }
+
+ public double getMaxLoadResistance() {
+ double val = ((mMaxLoadResistance&0xf8)>>3);
+ val = 5 * (val+1);
+ Log.v(LOGTAG, "getMaxLoadResistance<=" + val);
+ if (val > 55) val = 55.0;
+ return val;
+ }
+
+ public float getMaxDevicesSupported() {
+ int val = mMaxDevicesSupported +1;
+ Log.v(LOGTAG, "getMaxDevicesSupported<=" + val);
+ if (val > 8) val = 8;
+ return val;
+ }
+
+ public short getId() {
+ return mId;
+ }
+
+ public int getPtuClass() {
+ return (mClass > 4) ? 5 : (mClass+1);
+ }
+
+ public byte getHwRev () {
+ return mHwRev;
+ }
+
+ public byte getFwRev () {
+ return mFwRev;
+ }
+
+ public byte getProtocolRev () {
+ return mProtocolRev;
+ }
+ }
+
+ public static String toHex(int num) {
+ return String.format("0x%8s", Integer.toHexString(num)).replace(' ', '0');
+ }
+
+ private class PruControl {
+ public byte mEnable;
+ public byte mPermission;
+ public byte mTimeSet;
+ public short mReserved;
+ public PruControl () {
+ mEnable = 0x0;
+ mPermission = 0x0;
+ mTimeSet = 0x0;
+ mReserved = 0x0;
+ mReserved = 0x0;
+ }
+
+ public void print() {
+ Log.v(LOGTAG, "mEnable: " + toHex(mEnable));
+ Log.v(LOGTAG, "mPermission: " + toHex(mPermission));
+ Log.v(LOGTAG, "mTimeSet: " + toHex(mTimeSet));
+ Log.v(LOGTAG, "mReserved: " + toHex(mReserved));
+ }
+
+ public void setValue(byte[] value) {
+ mEnable = (byte)value[0];
+ mPermission = (byte)value[1];
+ mTimeSet = (byte)value[2];
+ mReserved = (short)(value[3] & 0xFF);
+ mReserved = (short)((value[4] & 0xFF) << 8);
+ return;
+ }
+
+ public byte[] getValue() {
+ byte[] res = new byte[5];
+ res[0] = mEnable;
+ res[1] = mPermission;
+ res[2] = mTimeSet;
+ res[3] = (byte)(LSB_MASK & mReserved);
+ res[4] = (byte)(MSB_MASK & mReserved);;
+ return res;
+ }
+
+ public boolean getEnablePruOutput() {
+ if ((mEnable&0x80) == 0x80) return true;
+ else return false;
+ }
+
+ public boolean getEnableCharger() {
+ if ((mEnable&0x40) == 0x40) return true;
+ else return false;
+ }
+
+ /* returns 0 Maximum power
+ 1 66%
+ 2 33%
+ */
+ public PowerLevel getReducePower() {
+ PowerLevel res = PowerLevel.POWER_LEVEL_MINIMUM;
+ int val = ((mEnable & 0x30) >> 4 );
+ if (val == 0) {
+ res = PowerLevel.POWER_LEVEL_MAXIMUM;
+ } else if (val == 1 && val == 3) {
+ res = PowerLevel.POWER_LEVEL_MEDIUM;
+ } else if (val == 2) {
+ res = PowerLevel.POWER_LEVEL_MINIMUM;
+ }
+ return res;
+ }
+
+ /* returns 0x00 permitted without reason
+ 0x01 Permitted with waiting time due to limited affordable power
+ 0x80 Denied with system error 3
+ 0x81 Denied due to limited affordable power
+ 0x82 Denied due to limited PTU Number of Devices
+ 0x83 Denied due to limited PTU Class support
+ */
+ public boolean getPermission() {
+
+ Log.v(LOGTAG, "getPermission" + mPermission);
+ if ((mPermission&0x80) == 0x80) return false;
+ else return true;
+ }
+
+ /* returns time in ms */
+ public int getSetTime() {
+ return (mTimeSet*10);
+ }
+ };
+
+ private PruAlert mPruAlert;
+ private PruControl mPruControl;
+ private PruStaticParam mPruStaticParam; //20 bytes
+ private PtuStaticParam mPtuStaticParam; //20 bytes
+ private static WipowerDynamicParam mPruDynamicParam; //20 bytes
+ private WipowerManager mWipowerManager;
+ private WbcManager mWbcManager;
+
+ public A4wpService() {
+ Log.v(LOGTAG, "A4wpService");
+ }
+
+ static private void cleanupService() {
+ Log.v(LOGTAG, "cleanupService");
+ }
+
+ private int processPruControl(byte[] value) {
+ int status = 0;
+
+ Log.v(LOGTAG, "processPruControl>");
+ if (value != null) {
+ mPruControl.setValue(value);
+ } else {
+ Log.e(LOGTAG, "control value is null");
+ return status;
+ }
+ mPruControl.print();
+
+ if (mWipowerManager == null) {
+ Log.e(LOGTAG, "mWipowerManager is null");
+ return status;
+ }
+
+ if (mPruControl.getEnablePruOutput()) {
+ Log.v(LOGTAG, "do Enable PruOutPut");
+ /* Wake lock is enabled by default, to disbale need to set property */
+ if(SystemProperties.getBoolean("persist.a4wp.skipwakelock", false) == false) {
+ /* Hold wake lock during connection */
+ acquire_wake_lock(true);
+ }
+ mOutputControl = true;
+ } else {
+ Log.v(LOGTAG, "do Disable PruOutPut");
+ if (mChargeComplete == true) {
+ mWipowerManager.enablePowerApply(true, true, true);
+ }
+ mWipowerManager.stopCharging();
+ isChargePortSet = false;
+ mOutputControl = false;
+ return status;
+ }
+
+ if (mPruControl.getEnableCharger()) {
+ Log.v(LOGTAG, "do Enable Charging");
+ } else {
+ Log.v(LOGTAG, "do Disable Charging");
+ }
+
+ PowerLevel val = mPruControl.getReducePower();
+ if (val == PowerLevel.POWER_LEVEL_MAXIMUM) {
+ Log.v(LOGTAG, "put to Max Power");
+ } else if (val == PowerLevel.POWER_LEVEL_MEDIUM){
+ Log.v(LOGTAG, "put to Medium Power");
+ } else if (val == PowerLevel.POWER_LEVEL_MINIMUM){
+ Log.v(LOGTAG, "put to Min Power");
+ }
+
+ mWipowerManager.setPowerLevel(val);
+
+ return status;
+ }
+
+ private int processPtuStaticParam(byte[] value) {
+ int status = 0;
+ Log.v(LOGTAG, "processPtuStaticParam>");
+ mPtuStaticParam = new PtuStaticParam(value);
+ mPtuStaticParam.print();
+
+ return status;
+ }
+
+ private static final byte CHARGE_COMPLETE_BIT = 0x08;
+
+ /**
+ * Wipower callbacks
+ */
+ private final WipowerManagerCallback mWipowerCallback = new WipowerManagerCallback() {
+
+ @Override
+ public void onWipowerReady() {
+ Log.v(LOGTAG, "onWipowerReady");
+ mWipowerManager.enablePowerApply(false, false, false);
+ if (mChargeComplete == true) {
+ mWipowerManager.enablePowerApply(true, true, true);
+ } else {
+ mWipowerManager.enablePowerApply(true, true, false);
+ }
+ mWipowerBoot = true;
+ }
+
+ @Override
+ public void onWipowerStateChange(WipowerState state) {
+ Log.v(LOGTAG, "onWipowerStateChange" + state);
+ }
+
+ @Override
+ public void onPowerApply(PowerApplyEvent state) {
+ Log.v(LOGTAG, "onPowerApply:" + state);
+
+ if (state == PowerApplyEvent.OFF) {
+ initiateDisconnection();
+ }
+ }
+
+ @Override
+ public void onWipowerAlert(byte alert) {
+ Log.v(LOGTAG, "onWipowerAlert: " + alert + " alert recieved");
+ mPruAlert.sendPruAlert(alert);
+ }
+
+
+ @Override
+ public void onWipowerData(WipowerDynamicParam data) {
+ Log.v(LOGTAG, "onWipowerData Alert");
+ byte[] value = data.getValue();
+ chkDynParamsAndStartCharging(value);
+ Log.v(LOGTAG, "calling SetValue");
+ mPruDynamicParam.setValue(value);
+ }
+
+ };
+
+ public static short toUnsigned(byte b) {
+ return (short)(b & 0xff);
+ }
+
+ /**
+ * GATT callbacks
+ */
+ private final BluetoothGattServerCallback mGattCallbacks = new BluetoothGattServerCallback() {
+ @Override
+ public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
+ WipowerState state = WipowerState.OFF;
+ if (newState == BluetoothProfile.STATE_DISCONNECTED) {
+ if (mWipowerManager != null && device.equals(mDevice)) {
+ Log.v(LOGTAG, "onConnectionStateChange:DISCONNECTED PrevState:" + " Device:" + device + " ChargeComplete:" + mChargeComplete);
+ mState = newState;
+ mDiscInitiated = false;
+ mOutputControl = false;
+ mWipowerManager.enableDataNotification(false);
+ mWipowerManager.enableAlertNotification(false);
+ mEnablePruAlerts = false;
+ mWipowerManager.stopCharging();
+ if (mChargeComplete != true) {
+ mWipowerManager.enablePowerApply(true, true, false);
+ }
+ if(SystemProperties.getBoolean("persist.a4wp.skipwakelock", false) == false) {
+ /* Drop wake lock once the connection is dropped gracefully */
+ acquire_wake_lock(false);
+ }
+ mDevice = null;
+ }
+ isChargePortSet = false;
+ mPruDynamicParam.resetValues();
+ } else if (newState == BluetoothProfile.STATE_CONNECTED) {
+ Log.v(LOGTAG, "onConnectionStateChange:CONNECTED");
+ }
+ }
+
+ @Override
+ public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
+ BluetoothGattCharacteristic characteristic,
+ boolean preparedWrite, boolean responseNeeded,
+ int offset, byte[] value) {
+
+ UUID id = characteristic.getUuid();
+ int status =0;
+
+ Log.v(LOGTAG, "onCharacteristicWriteRequest:" + id);
+ if (id == A4WP_PRU_CTRL_UUID && value.length == A4WP_PRU_CTRL_LENGTH)
+ {
+ status = processPruControl(value);
+ }
+ else if(id == A4WP_PTU_STATIC_UUID && value.length == A4WP_PTU_STATIC_LENGTH)
+ {
+ status = processPtuStaticParam(value);
+ }
+
+ if (responseNeeded == true) {
+ mBluetoothGattServer.sendResponse(device, requestId, status,
+ offset, value);
+ }
+ }
+
+ @Override
+ public void onDescriptorReadRequest(BluetoothDevice device, int requestId,
+ int offset, BluetoothGattDescriptor descriptor) {
+
+ UUID id = descriptor.getUuid();
+ byte[] value = {0};
+ int status = 0;
+
+ Log.v(LOGTAG, "onDescriptorReadRequest() - descriptor" + id);
+ if (id == A4WP_PRU_ALERT_DESC_UUID)
+ {
+ value = mPruAlert.getValue();
+ }
+
+
+ if (value != null)
+ {
+ Log.v(LOGTAG, "device=" + id + "requestId=" + requestId + "status=" + status + "offset=" + offset + "value=" + value[0]);
+ mBluetoothGattServer.sendResponse(device, requestId, status, offset, value);
+ }
+ }
+
+ @Override
+ public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
+ BluetoothGattDescriptor descriptor, boolean preparedWrite,
+ boolean responseNeeded, int offset, byte[] value) {
+
+ int status = 0;
+ UUID id = descriptor.getUuid();
+ Log.v(LOGTAG, "onDescriptorWriteRequest() - descriptor" + id);
+ if ((id == A4WP_PRU_ALERT_DESC_UUID) && (value.length == CCCD_LENGTH))
+ {
+ mDevice = device; // save the device as Notifications may need to be generated anytime now
+ status = mPruAlert.processPruAlertRequest(value);
+ } else
+ {
+ Log.v(LOGTAG, "onDescriptorWriteRequest() - Invalid descriptor: " + id + " OR length: " + value.length);
+ }
+
+ if (responseNeeded == true)
+ mBluetoothGattServer.sendResponse(device, requestId, status,
+ offset, value);
+ }
+
+ @Override
+ public void onCharacteristicReadRequest(BluetoothDevice device, int requestId,
+ int offset, BluetoothGattCharacteristic characteristic) {
+
+ UUID id = characteristic.getUuid();
+ byte[] value = {0};
+ int status = 0;
+
+ Log.v(LOGTAG, "onCharacteristicReadRequest:" + id);
+ if(id == A4WP_PRU_STATIC_UUID && mState == BluetoothProfile.STATE_DISCONNECTED)
+ {
+ mWipowerManager.enablePowerApply(false, false, false);
+ value = mPruStaticParam.getValue();
+ mDevice = device;
+ mState = BluetoothProfile.STATE_CONNECTED;
+ mWipowerManager.enableDataNotification(true);
+ }
+ else if (id == A4WP_PRU_DYNAMIC_UUID) {
+ if (mPruDynamicParam == null) {
+ Log.e(LOGTAG, "mPruDynamicParam is NULL");
+ return;
+ }
+ value = mPruDynamicParam.getValue();
+ if (mChargeComplete == true) {
+ value[PRU_ALERT] = (byte)(value[PRU_ALERT] | CHARGE_COMPLETE_BIT);
+ } else {
+ value[PRU_ALERT] = (byte)(value[PRU_ALERT] & (~CHARGE_COMPLETE_BIT));
+ }
+ value[OPTIONAL_FIELDS] = (byte)OPTIONAL_FIELD_MASK;
+ value[VRECT_MAX_LSB] = (byte)(LSB_MASK & DEFAULT_VRECT_MAX);
+ value[VRECT_MAX_MSB] = (byte)((MSB_MASK & DEFAULT_VRECT_MAX) >> 8);
+ if ((byte)(value[PRU_ALERT] & CHARGE_PORT_MASK) == CHARGE_PORT_MASK) {
+ value[VRECT_MIN_LSB] = (byte)(LSB_MASK & DEFAULT_VRECT_SET);
+ value[VRECT_MIN_MSB] = (byte)((MSB_MASK & DEFAULT_VRECT_SET) >> 8);
+ value[VRECT_SET_LSB] = (byte)(LSB_MASK & DEFAULT_VRECT_SET);
+ value[VRECT_SET_MSB] = (byte)((MSB_MASK & DEFAULT_VRECT_SET) >> 8);
+ } else {
+ value[VRECT_MIN_LSB] = (byte)(LSB_MASK & VRECT_MIN_CHG_DISABLED);
+ value[VRECT_MIN_MSB] = (byte)((MSB_MASK & VRECT_MIN_CHG_DISABLED) >> 8);
+ value[VRECT_SET_LSB] = (byte)(LSB_MASK & VRECT_MIN_CHG_DISABLED);
+ value[VRECT_SET_MSB] = (byte)((MSB_MASK & VRECT_MIN_CHG_DISABLED) >> 8);
+ }
+ }
+ else if (id == A4WP_PRU_CTRL_UUID) {
+ if (mPruControl == null) {
+ Log.e(LOGTAG, "mPruControl is NULL");
+ return;
+ }
+ value = mPruControl.getValue();
+ }
+ if (mBluetoothGattServer != null) {
+ mBluetoothGattServer.sendResponse(device, requestId, status, offset, value);
+ }
+ }
+
+ @Override
+ public void onServiceAdded(final int status, BluetoothGattService service) {
+ Log.i(LOGTAG, "Service added");
+ }
+ };
+
+ private void closeServer() {
+ if (mBluetoothGattServer != null) {
+ if (mDevice != null) mBluetoothGattServer.cancelConnection(mDevice);
+ mBluetoothGattServer.close();
+ }
+ }
+
+ private final class myAdvertiseCallback extends AdvertiseCallback {
+ private int mIndex;
+
+ myAdvertiseCallback(int index) {
+ mIndex = index;
+ }
+
+ @Override
+ public void onStartSuccess(AdvertiseSettings settingsInEffect) {
+ Log.d(LOGTAG, "advertise success " + mIndex);
+ if (mWipowerManager != null) {
+ mWipowerManager.enablePowerApply(false, false, false);
+ if (mChargeComplete == true) {
+ mWipowerManager.enablePowerApply(true, true, true);
+ } else {
+ mWipowerManager.enablePowerApply(true, true, false);
+ }
+ }
+ }
+
+ @Override
+ public void onStartFailure(int errorCode) {
+ Log.d(LOGTAG, "advetise failure " + mIndex);
+ }
+ }
+
+
+ private void StartAdvertising()
+ {
+ /* serviceData represnts service data for Wipower that needs
+ to be part of advertising,
+ 0x28 i& 0x00 represents the primary based handle
+ 0xFF and 0x60 represents:
+ ADV Flags are set to: CAT3 PRU 21, Reboot bit and OVP indicator
+ */
+ byte[] serviceData = new byte[] {
+ 0x28, 0x00, (byte)0xff, 0x60 };
+
+ mAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
+ mAdvertisementData = new AdvertiseData.Builder()
+ .addServiceData(uuid1, serviceData).build();
+
+ mAdvertiseSettings = new AdvertiseSettings.Builder()
+ .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
+ .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
+ .setConnectable(true).build();
+
+ Log.d(LOGTAG, " Calling mAdvertiser.startAdvertising");
+ if(mAdvertiser != null)
+ mAdvertiser.startAdvertising(mAdvertiseSettings, mAdvertisementData, mAdvertiseCallback);
+ else
+ Log.d(LOGTAG, " mAdvertiser is null");
+ }
+
+ private void stopAdvertising()
+ {
+ /* to be completed */
+ if (mAdvertiseCallback != null && mAdvertiser != null) {
+ mAdvertiser.stopAdvertising(mAdvertiseCallback);
+ }
+ }
+
+ private boolean startServer() {
+ BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
+ if (bluetoothManager == null) return false;
+
+ mBluetoothGattServer = bluetoothManager.openGattServer(this, mGattCallbacks);
+ Log.d(LOGTAG,"calling start server......");
+ if (mBluetoothGattServer == null) {
+ Log.e(LOGTAG,"mBluetoothGattServer is NULL");
+ return false;
+ }
+
+ BluetoothGattCharacteristic pruControl = new BluetoothGattCharacteristic(
+ A4WP_PRU_CTRL_UUID,
+ BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_READ,
+ BluetoothGattCharacteristic.PERMISSION_WRITE |
+ BluetoothGattCharacteristic.PERMISSION_READ);
+
+ BluetoothGattCharacteristic ptuStatic = new BluetoothGattCharacteristic(
+ A4WP_PTU_STATIC_UUID,
+ BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_READ,
+ BluetoothGattCharacteristic.PERMISSION_WRITE |
+ BluetoothGattCharacteristic.PERMISSION_READ);
+
+ mPruAlertChar = new BluetoothGattCharacteristic(
+ A4WP_PRU_ALERT_UUID,
+ BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY,
+ BluetoothGattCharacteristic.PERMISSION_READ );
+
+ BluetoothGattCharacteristic pruStatic = new BluetoothGattCharacteristic(
+ A4WP_PRU_STATIC_UUID,
+ BluetoothGattCharacteristic.PROPERTY_READ,
+ BluetoothGattCharacteristic.PERMISSION_READ);
+
+ BluetoothGattCharacteristic pruDynamic = new BluetoothGattCharacteristic(
+ A4WP_PRU_DYNAMIC_UUID,
+ BluetoothGattCharacteristic.PROPERTY_READ,
+ BluetoothGattCharacteristic.PERMISSION_READ);
+
+
+ BluetoothGattDescriptor pruAlertDesc = new BluetoothGattDescriptor(
+ A4WP_PRU_ALERT_DESC_UUID,
+ BluetoothGattCharacteristic.PERMISSION_READ |
+ BluetoothGattCharacteristic.PERMISSION_WRITE);
+
+ mPruAlertChar.addDescriptor(pruAlertDesc);
+
+ BluetoothGattService a4wpService = new BluetoothGattService(
+ A4WP_SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY);
+
+ a4wpService.addCharacteristic(pruControl);
+ a4wpService.addCharacteristic(ptuStatic);
+ a4wpService.addCharacteristic(mPruAlertChar);
+ a4wpService.addCharacteristic(pruStatic);
+ a4wpService.addCharacteristic(pruDynamic);
+
+
+ mBluetoothGattServer.addService(a4wpService);
+ Log.d(LOGTAG, "calling StartAdvertising");
+ StartAdvertising();
+
+ return true;
+ }
+
+ @Override
+ public void onCreate() {
+ Log.v(LOGTAG, "onCreate");
+ super.onCreate();
+
+ // Ensure Bluetooth is enabled
+ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) {
+ Log.d(LOGTAG, "Bluetooth is not available or enabled - exiting...");
+ return;
+ }
+
+ Log.v(LOGTAG, "calling startService");
+ startServer();
+ //Initialize PRU Static param
+ mPruStaticParam = new PruStaticParam();
+ mPruDynamicParam = new WipowerDynamicParam();
+ mPruAlert = new PruAlert((byte)0);
+ mPruControl = new PruControl();
+
+ mWipowerManager = WipowerManager.getWipowerManger(this, mWipowerCallback);
+ if (mWipowerManager != null)
+ mWipowerManager.registerCallback(mWipowerCallback);
+ mWbcManager = WbcManager.getInstance();
+ if (mWbcManager != null) {
+ mChargeComplete = (mWbcManager.getChargingRequired() == 0);
+ Log.v(LOGTAG, "onCreate: charge complete " + mChargeComplete);
+ mWbcManager.register(mWbcCallback);
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.v(LOGTAG, "onDestroy");
+ if (mWipowerManager != null)
+ mWipowerManager.unregisterCallback(mWipowerCallback);
+ if (mWbcManager != null)
+ mWbcManager.unregister(mWbcCallback);
+ if(SystemProperties.getBoolean("persist.a4wp.skipwakelock", false) == false) {
+ //release wake lock during BT-OFF.
+ acquire_wake_lock(false);
+ }
+ mOutputControl = false;
+ isChargePortSet = false;
+ }
+
+ @Override
+ public IBinder onBind(Intent in) {
+ Log.v(LOGTAG, "onBind");
+ return null;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ Log.d(LOGTAG, "onStart Command called!!");
+
+ //mWipowerBoot is used to hold power enable command till the service is been registered completely
+ if (mWipowerBoot == true && mWipowerManager != null) {
+ if (mChargeComplete == true) {
+ mWipowerManager.enablePowerApply(true, true, true);
+ } else {
+ mWipowerManager.enablePowerApply(true, true, false);
+ }
+ }
+ if(SystemProperties.getBoolean("persist.a4wp.skipwakelock", false) == false) {
+ //release wake lock in case if held during crashes or on BT restart.
+ acquire_wake_lock(false);
+ }
+ return START_STICKY;
+ }
+}
diff --git a/wipower-host/a4wp/src/org/codeaurora/bluetooth/a4wp_app/BTEventHandler.java b/wipower-host/a4wp/src/org/codeaurora/bluetooth/a4wp_app/BTEventHandler.java
new file mode 100644
index 0000000..d59d5f6
--- /dev/null
+++ b/wipower-host/a4wp/src/org/codeaurora/bluetooth/a4wp_app/BTEventHandler.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bt_wipower.a4wp;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import java.lang.Object;
+
+public class BTEventHandler extends BroadcastReceiver {
+ private static final String TAG = "BTEventHandler";
+ private static final boolean V = true/*Constants.VERBOSE*/;
+ private int state;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if(SystemProperties.getBoolean("persist.bluetooth.a4wp", false) == false) {
+ Log.e(TAG, "A4WP is not supported");
+ return;
+ }
+
+ String action = intent.getAction();
+
+
+ if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
+ state = intent.getIntExtra
+ (BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
+ if (BluetoothAdapter.STATE_ON == state) {
+ if (V) Log.v(TAG, "Received BLUETOOTH_STATE_ON");
+ ComponentName service = context.startService
+ (new Intent(context, A4wpService.class));
+ if (service != null) {
+ Log.e(TAG, "A4wp service started successfully");
+ } else {
+ Log.e(TAG, "Could Not Start A4wp Service");
+ return;
+ }
+ } else if (BluetoothAdapter.STATE_OFF == state) {
+ if (V) Log.v(TAG, "Received BLUETOOTH_STATE_OFF");
+ context.stopService(new Intent(context, A4wpService.class));
+
+ }
+ }
+ }
+}
diff --git a/wipower-host/a4wp/src/org/codeaurora/bluetooth/wipower/BTEventHandler.java b/wipower-host/a4wp/src/org/codeaurora/bluetooth/wipower/BTEventHandler.java
new file mode 100644
index 0000000..b191448
--- /dev/null
+++ b/wipower-host/a4wp/src/org/codeaurora/bluetooth/wipower/BTEventHandler.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bt_wipower.wipower;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import java.lang.Object;
+
+public class BTEventHandler extends BroadcastReceiver {
+ private static final String TAG = "BTEventHandler";
+ private static final boolean V = false/*Constants.VERBOSE*/;
+ private int state;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if(SystemProperties.getBoolean("ro.bluetooth.wipower", false) == false) {
+ Log.e(TAG, "WipowerService is not supported");
+ return;
+ }
+
+ String action = intent.getAction();
+
+ if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
+ state = intent.getIntExtra
+ (BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
+ if (BluetoothAdapter.STATE_ON == state) {
+ if (V) Log.e(TAG, "Received BLUETOOTH_STATE_ON");
+
+ ComponentName service = context.startService
+ (new Intent(context, WipowerService.class));
+ if (service != null) {
+ Log.e(TAG, "WipowerService started successfully");
+ } else {
+ Log.e(TAG, "Could Not Start Wipower Service ");
+ return;
+ }
+
+
+ } else if (BluetoothAdapter.STATE_OFF == state) {
+ if (V) Log.v(TAG, "Received BLUETOOTH_STATE_OFF");
+ context.stopService(new Intent(context, WipowerService.class));
+ }
+ }
+ }
+}
diff --git a/wipower-host/a4wp/src/org/codeaurora/bluetooth/wipower/WipowerApp.java b/wipower-host/a4wp/src/org/codeaurora/bluetooth/wipower/WipowerApp.java
new file mode 100644
index 0000000..d9127f3
--- /dev/null
+++ b/wipower-host/a4wp/src/org/codeaurora/bluetooth/wipower/WipowerApp.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @hide
+ */
+
+package org.codeaurora.bt_wipower.wipower;
+
+import android.app.Application;
+import android.util.Log;
+
+public class WipowerApp extends Application {
+ private static final String TAG = "BluetoothWipowerApp";
+ private static final boolean DBG = true;
+
+ static {
+ if (DBG) Log.d(TAG,"Loading JNI Library");
+ System.loadLibrary("wipower_jni");
+ }
+}
diff --git a/wipower-host/a4wp/src/org/codeaurora/bluetooth/wipower/WipowerService.java b/wipower-host/a4wp/src/org/codeaurora/bluetooth/wipower/WipowerService.java
new file mode 100644
index 0000000..bda73be
--- /dev/null
+++ b/wipower-host/a4wp/src/org/codeaurora/bluetooth/wipower/WipowerService.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.bt_wipower.wipower;
+
+import java.util.UUID;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCallback;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattDescriptor;
+import android.bluetooth.BluetoothGattService;
+import android.bluetooth.BluetoothGattServer;
+import android.bluetooth.BluetoothGattServerCallback;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.app.Service;
+import android.net.Credentials;
+import java.io.OutputStream;
+import android.util.Log;
+import android.os.IBinder;
+import android.content.Intent;
+import android.os.Process;
+import java.nio.ByteBuffer;
+import android.wipower.IWipower;
+import android.wipower.IWipowerManagerCallback;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+
+/**
+ * Class which executes A4WP service
+ */
+public class WipowerService extends Service
+{
+ private static final String LOGTAG = "WipowerService";
+ private static OutputStream mOutputStream = null;
+ private BluetoothAdapter mBluetoothAdapter = null;
+ private BluetoothGattServer mBluetoothGattServer = null;
+ private BluetoothDevice mDevice = null;
+
+ private static final Object mLock = new Object();
+ private int mState = BluetoothProfile.STATE_DISCONNECTED;
+
+ public boolean startCharging() {
+ int ret = enableNative(true);
+ return (ret==0) ? true : false;
+ }
+
+ public boolean stopCharging() {
+ int ret = enableNative(false);
+ return (ret==0) ? true : false;
+ }
+
+ public int getState() {
+ int ret = getStateNative();
+ return ret;
+ }
+
+ public boolean setCurrentLimit(byte value) {
+ int ret = setCurrentLimitNative(value);
+ return (ret==0) ? true : false;
+ }
+
+ public byte getCurrentLimit() {
+ byte ret = getCurrentLimitNative();
+ return ret;
+ }
+
+ public boolean enableAlert(boolean enable) {
+ int ret = enableAlertNative(enable);
+ return (ret==0) ? true : false;
+ }
+
+ public boolean enableData(boolean enable) {
+ int ret = enableDataNative(enable);
+ return (ret==0) ? true : false;
+ }
+
+ public boolean enablePowerApply(boolean enable, boolean on, boolean time_flag) {
+ Log.v(LOGTAG, "enablePowerApply: Calling Native enablei: " + enable + " on: " + on);
+ int ret = enablePowerApplyNative(enable, on, time_flag);
+ return (ret==0) ? true : false;
+ }
+
+ public void registerCallback(IWipowerManagerCallback callback) {
+ mCallbacks.register(callback);
+ }
+
+ public void unregisterCallback(IWipowerManagerCallback callback) {
+ mCallbacks.unregister(callback);
+ }
+
+ private static class WipowerBinder extends IWipower.Stub {
+ private WipowerService mService;
+
+ public WipowerBinder(WipowerService svc) {
+ Log.e(LOGTAG, ">In Constructor");
+ mService = svc;
+ }
+
+ public WipowerService getService() {
+ if (mService != null && mService.isAvailable()) {
+ return mService;
+ }
+ return null;
+ }
+
+ public boolean startCharging() {
+ boolean ret = false;
+ if (mService == null) {
+ Log.e(LOGTAG, "startCharging:Service not found");
+ } else {
+ ret = mService.startCharging();
+ }
+ return ret;
+ }
+
+ public boolean stopCharging() {
+ boolean ret = false;
+ if (mService == null) {
+ Log.e(LOGTAG, "stopCharging:Service not found");
+ } else {
+ ret = mService.stopCharging();
+ }
+ return ret;
+ }
+
+ public int getState() {
+ int ret = -1;
+ if (mService == null) {
+ Log.e(LOGTAG, "getState:Service not found");
+ } else {
+ ret = mService.getState();
+ }
+
+ return ret;
+ }
+
+ public boolean setCurrentLimit(byte value) {
+ boolean ret = false;
+ if (mService == null) {
+ Log.e(LOGTAG, "setCurrentLimit:Service not found");
+ } else {
+ ret = mService.setCurrentLimit(value);
+ }
+
+ return ret;
+ }
+
+ public byte getCurrentLimit() {
+ byte value = (byte)0xff;
+ if (mService == null) {
+ Log.e(LOGTAG, "getCurrentLimit:Service not found");
+ } else {
+ value = mService.getCurrentLimit();
+ }
+ return value;
+ }
+
+ public boolean enableAlert(boolean enable) {
+ boolean ret = false;
+ if (mService == null) {
+ Log.e(LOGTAG, "enableAlert:Service not found");
+ } else {
+ ret = mService.enableAlert(enable);
+ }
+ return ret;
+ }
+
+ public boolean enableData(boolean enable) {
+ boolean ret = false;
+ if (mService == null) {
+ Log.e(LOGTAG, "enableData:Service not found");
+ } else {
+ ret = mService.enableData(enable);
+ }
+ return ret;
+ }
+
+ public boolean enablePowerApply(boolean enable, boolean on, boolean time_flag) {
+ boolean ret = false;
+ Log.v(LOGTAG, "enablePowerApply: binder");
+ if (mService == null) {
+ Log.e(LOGTAG, "enableData:Service not found");
+ } else {
+ ret = mService.enablePowerApply(enable, on, time_flag);
+ }
+ return ret;
+ }
+
+
+ public void registerCallback(IWipowerManagerCallback callback) {
+ if (mService == null) {
+ Log.e(LOGTAG, "registerCallback:Service not found");
+ } else {
+ mService.registerCallback(callback);
+ }
+
+ }
+
+ public void unregisterCallback(IWipowerManagerCallback callback) {
+ if (mService == null) {
+ Log.e(LOGTAG, "unregisterCallback:Service not found");
+ } else {
+ mService.unregisterCallback(callback);
+ }
+ }
+
+ };
+
+ private WipowerBinder mBinder;
+ private RemoteCallbackList<IWipowerManagerCallback> mCallbacks;
+
+ public WipowerService() {
+ Log.v(LOGTAG, "WipowerService");
+
+ }
+
+ private boolean isAvailable() {
+ return false;
+ }
+
+ static private void cleanupService() {
+ Log.v(LOGTAG, "cleanupService");
+ }
+
+ @Override
+ public void onCreate() {
+ Log.v(LOGTAG, "onCreate");
+ super.onCreate();
+
+ mCallbacks = new RemoteCallbackList<IWipowerManagerCallback>();
+ mBinder = new WipowerBinder(this);
+ Log.v(LOGTAG, "onCreate>>");
+
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.v(LOGTAG, "onDestroy");
+ }
+
+ @Override
+ public IBinder onBind(Intent in) {
+ Log.v(LOGTAG, "onBind");
+ return mBinder;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ Log.d(LOGTAG, "onStart Command called!!");
+
+ Log.v(LOGTAG, "Calling classInitNative");
+ classInitNative();
+
+ Log.v(LOGTAG, "Calling InitNative");
+ initNative();
+ //Make this restarable service by
+ //Android app manager
+ return START_NOT_STICKY;
+ }
+
+
+ void stateChangeCallback (int state) {
+ Log.e(LOGTAG, "stateChangeCallback: " + state);
+ if (mCallbacks !=null) {
+ int n = mCallbacks.beginBroadcast();
+ Log.v(LOGTAG,"Broadcasting updateAdapterState() to " + n + " receivers.");
+ for (int i=0; i <n;i++) {
+ try {
+ mCallbacks.getBroadcastItem(i).onWipowerStateChange(state);
+ } catch (RemoteException e) {
+ Log.e(LOGTAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
+ }
+ }
+ mCallbacks.finishBroadcast();
+ }
+ }
+
+ void wipowerAlertNotify (int alert) {
+ Log.e(LOGTAG, "wipowerAlertNotify: " + alert);
+
+ if (mCallbacks !=null) {
+ int n=mCallbacks.beginBroadcast();
+ Log.d(LOGTAG,"Broadcasting wipower alert() to " + n + " receivers.");
+ for (int i=0; i <n;i++) {
+ try {
+ mCallbacks.getBroadcastItem(i).onWipowerAlert((byte)alert);
+ } catch (RemoteException e) {
+ Log.e(LOGTAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
+ }
+ }
+ mCallbacks.finishBroadcast();
+ }
+ }
+
+ void wipowerPowerNotify (byte alert) {
+ Log.e(LOGTAG, "wipowerPowerNotify: " + alert);
+
+ if (mCallbacks !=null) {
+ int n=mCallbacks.beginBroadcast();
+ Log.d(LOGTAG,"Broadcasting wipower power alert() to " + n + " receivers.");
+ for (int i=0; i <n;i++) {
+ try {
+ mCallbacks.getBroadcastItem(i).onPowerApply((byte)alert);
+ } catch (RemoteException e) {
+ Log.e(LOGTAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
+ }
+ }
+ mCallbacks.finishBroadcast();
+ }
+ }
+
+
+ void wipowerDataNotify (byte[] data) {
+ Log.e(LOGTAG, "wipowerDataNotify: " + data);
+
+ if (mCallbacks !=null) {
+ int n = mCallbacks.beginBroadcast();
+ Log.d(LOGTAG,"Broadcasting wipowerdata() to " + n + " receivers.");
+ for (int i=0; i <n;i++) {
+ try {
+ mCallbacks.getBroadcastItem(i).onWipowerData(data);
+ } catch (RemoteException e) {
+ Log.e(LOGTAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
+ }
+
+ }
+ mCallbacks.finishBroadcast();
+ }
+ }
+
+ private native static void classInitNative();
+ private native void initNative();
+ private native int enableNative(boolean enable);
+ private native int setCurrentLimitNative(byte value);
+ private native byte getCurrentLimitNative();
+ private native int getStateNative();
+ private native int enableAlertNative(boolean enable);
+ private native int enableDataNative(boolean enable);
+ private native int enablePowerApplyNative(boolean enable, boolean on, boolean time_flag);
+
+}
diff --git a/wipower-host/jni/Android.mk b/wipower-host/jni/Android.mk
new file mode 100644
index 0000000..e44ce54
--- /dev/null
+++ b/wipower-host/jni/Android.mk
@@ -0,0 +1,30 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_SRC_FILES:= \
+ android_hardware_wipower.cpp \
+
+LOCAL_C_INCLUDES += \
+ $(JNI_H_INCLUDE) \
+ packages/apps/Bluetooth/jni
+
+
+LOCAL_REQUIRED_MODULES := bluetooth.default
+
+LOCAL_PROGUARD_ENABLED := disabled
+
+
+LOCAL_SHARED_LIBRARIES := \
+ libnativehelper \
+ libandroid_runtime \
+ libcutils \
+ liblog \
+ libhardware
+
+LOCAL_MULTILIB := 32
+LOCAL_JNI_SHARED_LIBRARIES := libbluetooth_jni
+
+LOCAL_MODULE := libwipower_jni
+include $(BUILD_SHARED_LIBRARY)
diff --git a/wipower-host/jni/android_hardware_wipower.cpp b/wipower-host/jni/android_hardware_wipower.cpp
new file mode 100644
index 0000000..01d5f08
--- /dev/null
+++ b/wipower-host/jni/android_hardware_wipower.cpp
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LOG_TAG "wipower"
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "utils/Log.h"
+#include "utils/misc.h"
+#include <cutils/properties.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "android_hardware_wipower.h"
+#include "com_android_bluetooth.h"
+
+#define CHECK_CALLBACK_ENV \
+ if (!checkCallbackThread()) { \
+ ALOGE("Callback: '%s' is not called on the correct thread", __FUNCTION__);\
+ return; \
+ }
+
+#define DBG false
+
+namespace android {
+
+
+static jmethodID method_wipowerstateChangeCallback;
+static jmethodID method_wipowerAlertNotify;
+static jmethodID method_wipowerDataNotify;
+static jmethodID method_wipowerPowerNotify;
+
+static const wipower_interface_t *sWipowerInterface = NULL;
+static jobject sCallbacksObj;
+static JNIEnv *sCallbackEnv = NULL;
+
+static const bt_interface_t *sBluetoothInterface = NULL;
+
+
+JNIEnv* getCallbackEnv() {
+ return sCallbackEnv;
+}
+
+const bt_interface_t* getBluetoothInterface() {
+ return sBluetoothInterface;
+}
+
+static bool checkCallbackThread() {
+ sCallbackEnv = getCallbackEnv();
+
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (sCallbackEnv != env || sCallbackEnv == NULL) {
+ ALOGE("Callback env check fail: env: %p, callback: %p", env, sCallbackEnv);
+ return false;
+ }
+ return true;
+}
+
+
+static void wipower_state_changed_cb(wipower_state_t state) {
+ if (DBG)
+ ALOGV("%s: State is: %d", __FUNCTION__, state);
+ CHECK_CALLBACK_ENV
+ sCallbackEnv->CallVoidMethod(sCallbacksObj, method_wipowerstateChangeCallback, (jint) state);
+}
+
+static void wipower_alerts_cb(unsigned char alert_data) {
+ if (DBG)
+ ALOGV("%s: alert_data is: %d", __FUNCTION__, alert_data);
+ CHECK_CALLBACK_ENV
+ sCallbackEnv->CallVoidMethod(sCallbacksObj, method_wipowerAlertNotify, (jint) alert_data);
+}
+
+static void wipower_data_cb(wipower_dyn_data_t *alert_data) {
+ if (DBG)
+ ALOGV("%s: wp data is: %x", __FUNCTION__, (unsigned int)alert_data);
+ jbyteArray wp_data = NULL;
+
+ CHECK_CALLBACK_ENV
+ wp_data = sCallbackEnv->NewByteArray(sizeof(wipower_dyn_data_t));
+ if (wp_data == NULL) {
+ ALOGE("%s: alloc failure", __FUNCTION__);
+ return;
+ }
+
+ sCallbackEnv->SetByteArrayRegion(wp_data, 0, sizeof(wipower_dyn_data_t),
+ (jbyte*)alert_data);
+
+
+ sCallbackEnv->CallVoidMethod(sCallbacksObj, method_wipowerDataNotify, wp_data);
+
+ sCallbackEnv->DeleteLocalRef(wp_data);
+}
+
+static void wipower_power_cb(unsigned char alert_data) {
+ if (DBG)
+ ALOGV("%s: alert_data is: %d", __FUNCTION__, alert_data);
+ CHECK_CALLBACK_ENV
+ sCallbackEnv->CallVoidMethod(sCallbacksObj, method_wipowerPowerNotify, (jint) alert_data);
+}
+
+static void callback_thread_event(bt_cb_thread_evt event) {
+ JavaVM* vm = AndroidRuntime::getJavaVM();
+ ALOGE("Kiran: Callback thread attached: %d", event);
+ if (event == ASSOCIATE_JVM) {
+ JavaVMAttachArgs args;
+ char name[] = "wipower Service Callback Thread";
+ args.version = JNI_VERSION_1_6;
+ args.name = name;
+ args.group = NULL;
+ vm->AttachCurrentThread(&sCallbackEnv, &args);
+ ALOGE("Kiran: Callback thread attached: %p", sCallbackEnv);
+ } else if (event == DISASSOCIATE_JVM) {
+ if (!checkCallbackThread()) {
+ ALOGE("Kiran: Callback: '%s' is not called on the correct thread", __FUNCTION__);
+ return;
+ }
+ vm->DetachCurrentThread();
+ }
+}
+
+wipower_callbacks_t sWipowerCallbacks = {
+ sizeof(sWipowerCallbacks),
+ wipower_state_changed_cb,
+ wipower_alerts_cb,
+ wipower_data_cb,
+ wipower_power_cb,
+ callback_thread_event
+};
+
+
+static void android_wipower_wipowerJNI_classInitNative(JNIEnv* env, jclass clazz) {
+ int err;
+ hw_module_t* module;
+
+ ALOGE("%s:",__FUNCTION__);
+
+ method_wipowerstateChangeCallback = env->GetMethodID(clazz, "stateChangeCallback", "(I)V");
+
+ method_wipowerAlertNotify = env->GetMethodID(clazz, "wipowerAlertNotify", "(I)V");
+
+ method_wipowerDataNotify = env->GetMethodID(clazz, "wipowerDataNotify",
+ "([B)V");
+
+ method_wipowerPowerNotify = env->GetMethodID(clazz, "wipowerPowerNotify",
+ "(B)V");
+
+ ALOGE("%s: succesfully executed",__FUNCTION__);
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("bluetooth.mock_stack", value, "");
+
+ const char *id = (strcmp(value, "1")? BT_STACK_MODULE_ID : BT_STACK_TEST_MODULE_ID);
+
+ err = hw_get_module(id, (hw_module_t const**)&module);
+
+ if (err == 0) {
+ hw_device_t* abstraction;
+ err = module->methods->open(module, id, &abstraction);
+ if (err == 0) {
+ bluetooth_module_t* btStack = (bluetooth_module_t *)abstraction;
+ sBluetoothInterface = btStack->get_bluetooth_interface();
+ } else {
+ ALOGE("Error while opening Bluetooth library");
+ }
+ } else {
+ ALOGE("No Bluetooth Library found");
+ }
+
+}
+
+static void android_wipower_wipowerJNI_initNative (JNIEnv* env, jobject obj) {
+ if (DBG)
+ ALOGV("%s:",__FUNCTION__);
+
+ const bt_interface_t* btInf;
+
+ if ( (btInf = getBluetoothInterface()) == NULL) {
+ ALOGE("Bluetooth module is not loaded");
+ return;
+ }
+
+
+ //Get WiPower Interface
+ sWipowerInterface = (const wipower_interface_t*)btInf->get_profile_interface(WIPOWER_PROFILE_ID);
+ if (sWipowerInterface == NULL) {
+ ALOGE("%s: Get wipower interface: %x",__FUNCTION__, (unsigned int)sWipowerInterface);
+ return;
+ }
+ //Initialize wipower interface
+ int ret = sWipowerInterface->init(&sWipowerCallbacks);
+
+ if (ret != 0)
+ ALOGE("wipower init failed");
+
+ sCallbacksObj = env->NewGlobalRef(obj);
+}
+
+/* native interface */
+static jint android_wipower_wipowerJNI_enableNative
+ (JNIEnv* env, jobject thiz, jboolean enable)
+{
+ if (DBG)
+ ALOGD("%s->", __func__);
+
+ if (sWipowerInterface == NULL) {
+ ALOGE("No Interface initialized");
+ return JNI_FALSE;
+ }
+
+ int ret = sWipowerInterface->enable(enable);
+
+ if (ret != 0) {
+ ALOGE("wipower enable failed");
+ return JNI_FALSE;
+ } else {
+ ALOGE("wipower enabled successfully");
+ }
+ return 0;
+}
+
+/* native interface */
+static jint android_wipower_wipowerJNI_setCurrentLimitNative
+ (JNIEnv* env, jobject thiz, jbyte value)
+{
+ if (sWipowerInterface == NULL) {
+ ALOGE("No Interface initialized");
+ return JNI_FALSE;
+ }
+
+ int ret = sWipowerInterface->set_current_limit(value);
+
+ if (ret != 0) {
+ ALOGE("wipower set current limit failed");
+ return JNI_FALSE;
+ } else {
+ ALOGD("%s:success", __func__);
+ }
+
+ return 0;
+}
+
+/* native interface */
+static jbyte android_wipower_wipowerJNI_getCurrentLimitNative
+ (JNIEnv* env, jobject thiz)
+{
+
+ if (sWipowerInterface == NULL) {
+ ALOGE("No Interface initialized");
+ return JNI_FALSE;
+ }
+
+ unsigned char val = sWipowerInterface->get_current_limit();
+
+ ALOGV("%s: %d", __func__, val);
+
+ return val;
+}
+
+/* native interface */
+static jint android_wipower_wipowerJNI_getStateNative
+ (JNIEnv* env, jobject thiz)
+{
+
+ if (sWipowerInterface == NULL) {
+ ALOGE("No Interface initialized");
+ return JNI_FALSE;
+ }
+
+ int val = sWipowerInterface->get_state();
+
+ ALOGV("%s: %d", __func__, val);
+
+ return val;
+}
+
+/* native interface */
+static jint android_wipower_wipowerJNI_enableAlertNative
+ (JNIEnv* env, jobject thiz, jboolean enable)
+{
+
+ if (sWipowerInterface == NULL) {
+ ALOGE("No Interface initialized");
+ return JNI_FALSE;
+ }
+
+ int ret = sWipowerInterface->enable_alerts(enable);
+
+ if (ret != 0) {
+ ALOGE("%s: Failure", __func__);
+ return JNI_FALSE;
+ } else {
+ ALOGV("%s: Success", __func__);
+ }
+ return 0;
+}
+
+/* native interface */
+static jint android_wipower_wipowerJNI_enableDataNative
+ (JNIEnv* env, jobject thiz, jboolean enable)
+{
+
+ if (sWipowerInterface == NULL) {
+ ALOGE("No Interface initialized");
+ return JNI_FALSE;
+ }
+
+ int ret = sWipowerInterface->enable_data_notify(enable);
+
+ if (ret != 0) {
+ ALOGE("%s: Failure", __func__);
+ return JNI_FALSE;
+ } else {
+ ALOGV("%s: Success", __func__);
+ }
+
+ return 0;
+}
+
+/* native interface */
+static jint android_wipower_wipowerJNI_enablePowerApplyNative
+ (JNIEnv* env, jobject thiz, jboolean enable, jboolean on,
+ jboolean time_flag)
+{
+
+ if (sWipowerInterface == NULL) {
+ ALOGE("No Interface initialized");
+ return JNI_FALSE;
+ }
+
+ int ret = sWipowerInterface->enable_power_apply(enable, on, time_flag);
+
+ if (ret != 0) {
+ ALOGE("%s: Failure", __func__);
+ return JNI_FALSE;
+ } else {
+ ALOGV("%s: Success", __func__);
+ }
+
+ return 0;
+}
+
+/*
+ * JNI registration.
+ */
+static JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ { "classInitNative", "()V",
+ (void*)android_wipower_wipowerJNI_classInitNative},
+
+ { "initNative", "()V",
+ (void*)android_wipower_wipowerJNI_initNative},
+
+ { "enableNative", "(Z)I",
+ (void*)android_wipower_wipowerJNI_enableNative},
+
+ { "setCurrentLimitNative", "(B)I",
+ (void*)android_wipower_wipowerJNI_setCurrentLimitNative},
+
+ { "getCurrentLimitNative", "()B",
+ (void*)android_wipower_wipowerJNI_getCurrentLimitNative},
+
+ { "getStateNative", "()I",
+ (void*)android_wipower_wipowerJNI_getStateNative},
+
+ { "enableAlertNative", "(Z)I",
+ (void*)android_wipower_wipowerJNI_enableAlertNative},
+
+ { "enableDataNative", "(Z)I",
+ (void*)android_wipower_wipowerJNI_enableDataNative},
+
+ { "enablePowerApplyNative", "(ZZZ)I",
+ (void*)android_wipower_wipowerJNI_enablePowerApplyNative},
+};
+int register_android_hardware_wipower(JNIEnv* env)
+{
+
+ ALOGV("%s: >\n", __func__);
+ return jniRegisterNativeMethods(env, "org/codeaurora/bt_wipower/wipower/WipowerService", gMethods, NELEM(gMethods));
+}
+}
+
+jint JNI_OnLoad(JavaVM *jvm, void *reserved)
+{
+ JNIEnv *e;
+ int status;
+ ALOGE("Wipower : loading WIPOWER-JNI\n");
+
+ if(jvm->GetEnv((void **)&e, JNI_VERSION_1_6)) {
+ ALOGE("JNI version mismatch error");
+ return JNI_ERR;
+ }
+
+ if ((status = android::register_android_hardware_wipower(e)) < 0) {
+ ALOGE("jni adapter service registration failure, status: %d", status);
+ return JNI_ERR;
+ }
+ return JNI_VERSION_1_6;
+}
diff --git a/wipower-host/jni/android_hardware_wipower.h b/wipower-host/jni/android_hardware_wipower.h
new file mode 100644
index 0000000..eca9589
--- /dev/null
+++ b/wipower-host/jni/android_hardware_wipower.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef COM_ANDROID_WIPOWER_H
+#define COM_ANDROID_WIPOWER_H
+
+#include "JNIHelp.h"
+#include "jni.h"
+#include "hardware/hardware.h"
+#include "hardware/bluetooth.h"
+#include "hardware/wipower.h"
+
+namespace android {
+
+
+int register_android_hardware_wipower (JNIEnv* env);
+
+}
+
+#endif /* COM_ANDROID_WIPOWER_H */
+
diff --git a/wipower-host/wipower_lib/Android.mk b/wipower-host/wipower_lib/Android.mk
new file mode 100644
index 0000000..8b94fbe
--- /dev/null
+++ b/wipower-host/wipower_lib/Android.mk
@@ -0,0 +1,19 @@
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := android.wipower
+LOCAL_SRC_FILES := $(call all-java-files-under,.)
+LOCAL_SRC_FILES += android/wipower/IWipowerManagerCallback.aidl
+LOCAL_SRC_FILES += android/wipower/IWipower.aidl
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := android.wipower.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
+
diff --git a/wipower-host/wipower_lib/android.wipower.xml b/wipower-host/wipower_lib/android.wipower.xml
new file mode 100644
index 0000000..72413bc
--- /dev/null
+++ b/wipower-host/wipower_lib/android.wipower.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+-->
+
+<permissions>
+ <library name="android.wipower" file="/system/framework/android.wipower.jar"/>
+</permissions>
diff --git a/wipower-host/wipower_lib/android/wipower/IWipower.aidl b/wipower-host/wipower_lib/android/wipower/IWipower.aidl
new file mode 100644
index 0000000..b326628
--- /dev/null
+++ b/wipower-host/wipower_lib/android/wipower/IWipower.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package android.wipower;
+
+
+import android.wipower.IWipowerManagerCallback;
+import android.os.ParcelUuid;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * System private API for talking with the WiPower Manger.
+ *
+ * {@hide}
+ */
+interface IWipower
+{
+ int getState();
+ boolean startCharging();
+ boolean stopCharging();
+
+ boolean setCurrentLimit(in byte value);
+ byte getCurrentLimit();
+
+ boolean enableAlert(boolean enable);
+ boolean enableData(boolean enable);
+ boolean enablePowerApply(boolean enable, boolean on, boolean time_flag);
+
+ void registerCallback(in IWipowerManagerCallback callback);
+ void unregisterCallback(in IWipowerManagerCallback callback);
+
+}
diff --git a/wipower-host/wipower_lib/android/wipower/IWipowerManagerCallback.aidl b/wipower-host/wipower_lib/android/wipower/IWipowerManagerCallback.aidl
new file mode 100644
index 0000000..a2c1306
--- /dev/null
+++ b/wipower-host/wipower_lib/android/wipower/IWipowerManagerCallback.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package android.wipower;
+
+/**
+ * Application level callback for Wipower manager APIs.
+ *
+ * {@hide}
+ */
+interface IWipowerManagerCallback
+{
+ void onWipowerStateChange(int state);
+
+ void onWipowerAlert(byte alert);
+
+ void onWipowerData(in byte[] value);
+
+ void onPowerApply(byte value);
+}
diff --git a/wipower-host/wipower_lib/android/wipower/WipowerDynamicParam.java b/wipower-host/wipower_lib/android/wipower/WipowerDynamicParam.java
new file mode 100644
index 0000000..949c33a
--- /dev/null
+++ b/wipower-host/wipower_lib/android/wipower/WipowerDynamicParam.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+package android.wipower;
+
+import android.util.Log;
+
+import android.os.SystemProperties;
+
+
+/**
+ * Class holds the PRU Dynamic parameter and related attributes
+ *
+ * {@hide}
+ */
+
+public class WipowerDynamicParam {
+ private byte mOptValidity;
+ private short mRectVoltage;
+ private short mRectCurrent;
+ private short mOutputVoltage;
+ private short mOutputCurrent;
+ private byte mTemperature;
+ private short mMinRectVoltageDyn;
+ private short mMaxRectVoltageDyn;
+ private short mSetRectVoltageDyn;
+ private byte mAlert;
+ private short mReserved1;
+ private byte mReserved2;
+
+ private static final String LOGTAG = "WipowerDynamicParam";
+ private static boolean sDebug = false;
+
+ private static final int MSB_MASK = 0xFF00;
+ private static final int LSB_MASK = 0x00FF;
+
+ /* ADC conversions for voaltag and current */
+ private static final float VREG_ADC_TO_mV_RATIO = ((float)(2.44/256)*10000);
+ private static final float IREG_ADC_TO_mA_RATIO = ((float)(2.44/256)*500);
+
+ /* Over volatage protection parameters */
+ private static final byte OVP_BIT = (byte)0x80;
+ private static final short OVP_THRESHHOLD_VAL = 21500;
+
+
+ /**
+ * Default Constructor
+ * {@hide}
+ */
+ public WipowerDynamicParam() {
+ mOptValidity = 0x00;
+ mRectVoltage = 0x00;
+ mRectCurrent = 0x00;
+ mOutputVoltage = 0x00;
+ mOutputCurrent = 0x00;
+ mTemperature = 0x00;
+ mMinRectVoltageDyn = 0x00;
+ mMaxRectVoltageDyn = 0x00;
+ mSetRectVoltageDyn = 0x00;
+ mAlert = 0x00;
+ mReserved1 = 0;
+ mReserved2 = 0;
+ }
+
+ /**
+ * helper to convert num to hex
+ * {@hide}
+ */
+ private static String toHex(int num) {
+ return String.format("0x%8s", Integer.toHexString(num)).replace(' ', '0');
+ }
+
+ /**
+ * helper print function
+ * {@hide}
+ */
+ void print() {
+ sDebug = SystemProperties.getBoolean("persist.a4wp.logging", false);
+ if (sDebug) Log.v(LOGTAG, "mOptValidity " + toHex(mOptValidity) +
+ "mRectVoltage " + toHex(mRectVoltage) + "mRectCurrent " +
+ toHex(mRectCurrent) + "mOutputVoltage " + toHex(mOutputVoltage));
+ if (sDebug) Log.v(LOGTAG, "mOutputCurrent " + toHex(mOutputCurrent) +
+ "mTemperature " + toHex(mTemperature) + "mMinRectVoltageDyn " +
+ toHex(mMinRectVoltageDyn) + "mMaxRectVoltageDyn " + toHex(mMaxRectVoltageDyn));
+ if (sDebug) Log.v(LOGTAG, "mSetRectVoltageDyn " +
+ toHex(mSetRectVoltageDyn) + "mAlert " + toHex(mAlert) +
+ "mReserved1 " + toHex(mReserved1) + "mReserved2 " + toHex(mReserved2));
+ }
+
+ /**
+ * {@hide}
+ * Gets the PRU dynamic parameter values in bytes
+ *
+ * @return byte array of PRU Dynamic parameter
+ *
+ */
+ public byte[] getValue() {
+ byte[] res = new byte[20];
+ print();
+ res[0] = mOptValidity;
+ res[1] = (byte)(LSB_MASK & mRectVoltage);
+ res[2] = (byte)((MSB_MASK & mRectVoltage) >> 8);
+ res[3] = (byte)(LSB_MASK & mRectCurrent);
+ res[4] = (byte)((MSB_MASK & mRectCurrent) >> 8);
+ res[5] = (byte)(LSB_MASK & mOutputVoltage);
+ res[6] = (byte)((MSB_MASK & mOutputVoltage) >> 8);
+ res[7] = (byte)(LSB_MASK & mOutputCurrent);
+ res[8] = (byte)((MSB_MASK & mOutputCurrent) >> 8);
+ res[9] = mTemperature;
+ res[10] = (byte)(LSB_MASK & mMinRectVoltageDyn);
+ res[11] = (byte)((MSB_MASK & mMinRectVoltageDyn) >> 8);
+ res[12] = (byte)(LSB_MASK & mSetRectVoltageDyn);
+ res[13] = (byte)((MSB_MASK & mSetRectVoltageDyn) >> 8);
+ res[14] = (byte)(LSB_MASK & mMaxRectVoltageDyn);
+ res[15] = (byte)((MSB_MASK & mMaxRectVoltageDyn) >> 8);
+ res[16] = mAlert;
+ if (((res[16] & OVP_BIT) == OVP_BIT) && (mRectVoltage < OVP_THRESHHOLD_VAL))
+ res[16] = (byte)(res[16] & ~OVP_BIT);
+
+ Log.i(LOGTAG, "mPruDynamicParam.getValue");
+ return res;
+ }
+
+ public void resetValues() {
+ mOptValidity = 0x00;
+ mRectVoltage = 0x00;
+ mRectCurrent = 0x00;
+ mOutputVoltage = 0x00;
+ mOutputCurrent = 0x00;
+ mTemperature = 0x00;
+ mMinRectVoltageDyn = 0x00;
+ mMaxRectVoltageDyn = 0x00;
+ mSetRectVoltageDyn = 0x00;
+ mAlert = 0x00;
+ mReserved1 = 0x00;
+ mReserved2 = 0x00;
+ }
+
+ public static short toUnsigned(byte b) {
+ return (short)(b & 0xff);
+ }
+
+ public static short VREG_ADC_TO_mV(short adc){
+ return (short)((adc)*(VREG_ADC_TO_mV_RATIO));
+ }
+
+ public static short IREG_ADC_TO_mA(short adc) {
+ return (short)((adc)*(IREG_ADC_TO_mA_RATIO));
+ }
+
+ /**
+ * {@hide}
+ * Sets the PRU dynamic parameter values for A4WP App in bytes
+ *
+ * @return none
+ */
+ public void setValue(byte[] value) {
+
+ resetValues();
+ mOptValidity = value[0];
+ mRectVoltage = (short)toUnsigned(value[1]);
+ mRectVoltage |= (short)(toUnsigned(value[2]) << 8);
+ mRectCurrent = (short)toUnsigned(value[3]);
+ mRectCurrent |= (short)(toUnsigned(value[4]) << 8);
+ mOutputVoltage = (short)toUnsigned(value[5]);
+ mOutputVoltage |= (short)(toUnsigned(value[6]) << 8);
+ mOutputCurrent = (short)toUnsigned(value[7]);
+ mOutputCurrent |= (short)(toUnsigned(value[8]) << 8);
+ mTemperature = value[9];
+ mMinRectVoltageDyn = (short)toUnsigned(value[10]);
+ mMinRectVoltageDyn |= (short)(toUnsigned(value[11]) << 8);
+ mSetRectVoltageDyn = (short)toUnsigned(value[12]);
+ mSetRectVoltageDyn |= (short)(toUnsigned(value[13]) << 8);
+ mMaxRectVoltageDyn = (short)toUnsigned(value[14]);
+ mMaxRectVoltageDyn |= (short)(toUnsigned(value[15]) << 8);
+
+ mAlert = value[16];
+ mReserved1 = (short)(toUnsigned(value[17]));
+ mReserved1 = (short)(toUnsigned(value[18]) << 8);
+ mReserved2 = value[19];
+ Log.i(LOGTAG, "mPruDynamicParam.setAppValue");
+ print();
+ return;
+ }
+ }
+
diff --git a/wipower-host/wipower_lib/android/wipower/WipowerManager.java b/wipower-host/wipower_lib/android/wipower/WipowerManager.java
new file mode 100644
index 0000000..edbb7df
--- /dev/null
+++ b/wipower-host/wipower_lib/android/wipower/WipowerManager.java
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package android.wipower;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.IPackageManager;
+import android.os.IBinder;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+import android.os.SystemProperties;
+
+/**
+ * Public APIs for wipower control
+ * This class exposes APIs to control wipower module on the phone
+ * These APIs would be used by wireless charging application in context
+ * of Bluetooth A4WP profile
+ *
+ * {@hide}
+ */
+
+public final class WipowerManager {
+ private static final String TAG = "WipowerManager";
+ private static final boolean DBG = true;
+ private static final boolean VDBG = false;
+
+ private static IWipower mService;
+ private static ArrayList<WipowerManagerCallback> mCallbacks;
+ private static WipowerDynamicParam mPruData;
+ private static WipowerState mState;
+ private static WipowerManager mWipowerManager;
+
+ /**
+ * Power levels used to indicate the charging levels
+ *
+ * {@hide}
+ */
+ public enum PowerLevel {
+ POWER_LEVEL_MAXIMUM,
+ POWER_LEVEL_MEDIUM,
+ POWER_LEVEL_MINIMUM,
+ POWER_LEVEL_UNKNOWN
+ };
+
+ /**
+ * Wipower States
+ * {@hide}
+ */
+ public enum WipowerState {
+ OFF,
+ ON
+ };
+
+ /**
+ * Wipower power applied event
+ * {@hide}
+ */
+ public enum PowerApplyEvent {
+ OFF,
+ ON
+ };
+
+ /* helper function to invoke callbacks to application layer*/
+ void updateWipowerState(WipowerState state){
+ if (mCallbacks != null) {
+ int n = mCallbacks.size();
+ Log.v(TAG,"Broadcasting updateAdapterState() to " + n + " receivers.");
+ for (int i = 0; i < n; i++) {
+ mCallbacks.get(i).onWipowerStateChange(state);
+ }
+ }
+ }
+
+ /* helper function to invoke callbacks to application layer*/
+ void updateWipowerData(WipowerDynamicParam pruData){
+ if (mCallbacks != null) {
+ int n = mCallbacks.size();
+ Log.v(TAG,"Broadcasting updateWipowerData() to " + n + " receivers.");
+ for (int i = 0; i < n; i++) {
+ mCallbacks.get(i).onWipowerData(pruData);
+ }
+ }
+ }
+
+ /* helper function to invoke callbacks to application layer*/
+ void updateWipowerAlert(byte alert){
+ if (mCallbacks != null) {
+ int n = mCallbacks.size();
+ Log.v(TAG,"Broadcasting updateWipowerAlert() to " + n + " receivers.");
+ for (int i = 0; i < n; i++) {
+ mCallbacks.get(i).onWipowerAlert(alert);
+ }
+ }
+ }
+
+ void updatePowerApplyAlert(PowerApplyEvent alert){
+ if (mCallbacks != null) {
+ int n = mCallbacks.size();
+ if (VDBG) Log.v(TAG,"Broadcasting updatePowerApplyAlert() to " + n + " receivers.");
+ for (int i = 0; i < n; i++) {
+ mCallbacks.get(i).onPowerApply(alert);
+ }
+ }
+ }
+
+
+ /* helper function to invoke callbacks to application layer*/
+ void updateWipowerReady(){
+ if (mCallbacks != null) {
+ int n = mCallbacks.size();
+ if (VDBG) Log.v(TAG,"Broadcasting updateWipowerReady " + n + " receivers.");
+ for (int i = 0; i < n; i++) {
+ mCallbacks.get(i).onWipowerReady();
+ }
+ }
+ }
+
+ final private IWipowerManagerCallback mWiPowerMangerCallback =
+ new IWipowerManagerCallback.Stub() {
+
+ public void onWipowerStateChange(int state) {
+ WipowerState s;
+
+ if (state == 1) {
+ s = WipowerState.ON;
+ } else {
+ s = WipowerState.OFF;
+ }
+
+ Log.v(TAG, "onWipowerStateChange: state" + state);
+ updateWipowerState(s);
+ }
+
+ public void onWipowerAlert(byte alert) {
+ Log.v(TAG, "onWipowerAlert: alert" + alert);
+ updateWipowerAlert(alert);
+
+ }
+
+ public void onPowerApply(byte alert) {
+ PowerApplyEvent s;
+
+ if (alert == 0x1) {
+ s = PowerApplyEvent.ON;
+ } else {
+ s = PowerApplyEvent.OFF;
+ }
+
+ if (VDBG) Log.v(TAG, "onPowerApply: alert" + alert);
+ updatePowerApplyAlert(s);
+
+ }
+
+ public void onWipowerData(byte[] value) {
+ Log.v(TAG, "onWipowerData: " + value);
+ if (mPruData != null) {
+ mPruData.setValue(value);
+ updateWipowerData(mPruData);
+ } else {
+ Log.e(TAG, "mPruData is null");
+ }
+
+ }
+ };
+
+ private ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ mService = IWipower.Stub.asInterface(service);
+
+ if (DBG) Log.v(TAG, "Proxy object connected: " + mService);
+ try {
+ mService.registerCallback(mWiPowerMangerCallback);
+ } catch (android.os.RemoteException e) {
+ Log.e(TAG, "not able to register as client");
+ }
+
+ Log.v(TAG, "Calling onWipowerReady");
+ updateWipowerReady();
+
+ }
+ public void onServiceDisconnected(ComponentName className) {
+ if (DBG) Log.v(TAG, "Proxy object disconnected");
+ try {
+ mService.unregisterCallback(mWiPowerMangerCallback);
+ } catch (android.os.RemoteException e) {
+ Log.e(TAG, "not able to unregister as client");
+ }
+ mService = null;
+ }
+ };
+
+ public static synchronized WipowerManager getWipowerManger(Context context, WipowerManagerCallback callback) {
+ if (!isWipowerSupported()) {
+ Log.e(TAG, "Wipower not supported");
+ return null;
+ }
+
+ if (mWipowerManager == null) {
+ if (DBG) Log.v(TAG, "Instantiate Singleton");
+ mWipowerManager = new WipowerManager(context.getApplicationContext(), callback);
+ }
+ return mWipowerManager;
+ }
+
+ /**
+ * WipowerManager is the main class which exposes Application interfaces
+ * Wireless Charging control
+ *
+ * {@hide}
+ */
+ private WipowerManager(Context context, WipowerManagerCallback callback) {
+ if (mService == null) {
+ try {
+
+ Intent bindIntent = new Intent(IWipower.class.getName());
+ ComponentName comp = bindIntent.resolveSystemService(context.getPackageManager(), 0);
+ bindIntent.setComponent(comp);
+ if (comp == null || !context.bindService(bindIntent, mConnection, Context.BIND_AUTO_CREATE)) {
+ Log.e(TAG, "Could not bind to Wipower Service");
+ }
+ } catch (SecurityException e) {
+ Log.e(TAG, "Security Exception");
+ }
+ }
+
+ Log.v(TAG, "Bound to Wipower Service");
+ mPruData = new WipowerDynamicParam();
+ mCallbacks = new ArrayList<WipowerManagerCallback>();
+ }
+
+ static boolean isWipowerSupported() {
+
+ if (SystemProperties.getBoolean("ro.bluetooth.wipower", false) == true) {
+ Log.v(TAG, "System.getProperty is true");
+ return true;
+ } else {
+ Log.v(TAG, "System.getProperty is false");
+ return false;
+ }
+ }
+
+
+ /**
+ * startCharing initiate the wireless charging process by internally
+ * setting output voltage for the wireless charging module
+ * <p>This is an asynchronous call: Status of this indicated by
+ * {@link WipowerManagerCallback::onWipowerStateChange}
+ *
+ * @return true on sucess,
+ * false if start charging fails or if the hardware doesn't support this feature
+ * {@hide}
+ */
+ public boolean startCharging() {
+ boolean ret = false;
+
+ if (!isWipowerSupported()) {
+ Log.e(TAG, "Wipower not supported");
+ return false;
+ }
+
+ if (mService == null) {
+ Log.e(TAG, "startCharging: Service not available");
+ } else {
+ try {
+ ret = mService.startCharging();
+ } catch (android.os.RemoteException e) {
+ Log.e(TAG, "Service Exceptione");
+ }
+ }
+
+ return ret;
+ }
+
+ /**
+ * stopCharing stop the wireless charging process by internally
+ * setting output voltage for the wireless charging module
+ * <p>This is an asynchronous call: Status of this indicated by
+ * {@link WipowerManagerCallback::onWipowerStateChange}
+ *
+ * @return true on sucess
+ * false if start charging fails or if the hardware doesn't support this feature
+ * {@hide}
+ */
+ public boolean stopCharging() {
+ boolean ret = false;
+
+ if (!isWipowerSupported()) {
+ Log.e(TAG, "Wipower not supported");
+ return false;
+ }
+
+ if (mService == null) {
+ Log.e(TAG, " Wipower Service not available");
+ } else {
+ try {
+ ret = mService.stopCharging();
+ } catch (android.os.RemoteException e) {
+ Log.e(TAG, "Service Exceptione");
+ }
+ }
+
+ return ret;
+ }
+
+ /**
+ * Sets the current level for Wireless charging module
+ *
+ * @param {@link Powerlevel} indicating the desired power level
+ *
+ * @return true on success
+ * false if start charging fails or if the hardware doesn't support this feature
+ *
+ * {@hide}
+ */
+ public boolean setPowerLevel(PowerLevel powerlevel) {
+ boolean ret = false;
+
+ if (!isWipowerSupported()) {
+ Log.e(TAG, "Wipower not supported");
+ return false;
+ }
+
+ if (mService == null) {
+ Log.e(TAG, " Wipower Service not available");
+ } else {
+ byte level = 0;
+ if( powerlevel == PowerLevel.POWER_LEVEL_MINIMUM) level = 2;
+ else if( powerlevel == PowerLevel.POWER_LEVEL_MEDIUM) level = 1;
+ else if( powerlevel == PowerLevel.POWER_LEVEL_MAXIMUM) level = 0;
+ try {
+ ret = mService.setCurrentLimit(level);
+ } catch (android.os.RemoteException e) {
+ Log.e(TAG, "Service Exceptione");
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Gets the current level for Wireless charging module
+ *
+ * @return {@link Powerlevel} current power level
+ *
+ * {@hide}
+ */
+ public PowerLevel getPowerLevel() {
+ PowerLevel ret = PowerLevel.POWER_LEVEL_UNKNOWN;
+
+ if (mService == null) {
+ Log.e(TAG, " Wipower Service not available");
+ } else {
+ byte res = 0;
+ try {
+ res = mService.getCurrentLimit();
+ } catch (android.os.RemoteException e) {
+ Log.e(TAG, "Service Exceptione");
+ }
+ if(res == 0) ret = PowerLevel.POWER_LEVEL_MINIMUM;
+ else if(res == 1) ret = PowerLevel.POWER_LEVEL_MEDIUM;
+ else if(res == 2) ret = PowerLevel.POWER_LEVEL_MAXIMUM;
+ }
+ return ret;
+ }
+
+ /**
+ * Gets the current state of Wireless charging
+ *
+ * @return {@link WipowerState } wireless charging state
+ * {@hide}
+ */
+ public WipowerState getState() {
+ WipowerState ret = WipowerState.OFF;
+ if (mService == null) {
+ Log.e(TAG, " Wipower Service not available");
+ } else {
+ int res = 0;
+ try {
+ res = mService.getState();
+ } catch (android.os.RemoteException e) {
+ Log.e(TAG, "Service Exceptione");
+ }
+ if (res == 0) {
+ ret = WipowerState.OFF;
+ }
+ else {
+ ret = WipowerState.ON;
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Enables Alert notifications.
+ *
+ * @return true on success or flase otherwise
+ * {@hide}
+ */
+ public boolean enableAlertNotification(boolean enable) {
+ boolean ret = false;
+ if (mService == null) {
+ Log.e(TAG, "Service not available");
+ } else {
+ try {
+ ret = mService.enableAlert(enable);
+ } catch (android.os.RemoteException e) {
+ Log.e(TAG, "Service Exception");
+ }
+ }
+
+ return ret;
+ }
+
+ /**
+ * Enables data notifications.
+ *
+ * @return true on success or flase otherwise
+ * {@hide}
+ */
+ public boolean enableDataNotification(boolean enable) {
+ boolean ret = false;
+ if (mService == null) {
+ Log.e(TAG, "Service not available");
+ } else {
+ try {
+ ret = mService.enableData(enable);
+ } catch (android.os.RemoteException e) {
+ Log.e(TAG, "Service Exceptione");
+ }
+ }
+
+ return ret;
+ }
+
+ /**
+ * Enables power detection command.
+ *
+ * @return true on success or flase otherwise
+ * {@hide}
+ */
+ public boolean enablePowerApply(boolean enable, boolean on, boolean time_flag) {
+ boolean ret = false;
+ Log.v(TAG,"enablePowerApply: enable: " + enable + " on: " + on + " time_flag:" + time_flag);
+ if (mService == null) {
+ Log.e(TAG, "Service not available");
+ } else {
+ try {
+ ret = mService.enablePowerApply(enable, on, time_flag);
+ } catch (android.os.RemoteException e) {
+ Log.e(TAG, "Service Exceptione");
+ }
+ }
+
+ return ret;
+ }
+
+
+ /** API used to reigester the wipower callbacks.
+ * {@hide}
+ */
+ public void registerCallback(WipowerManagerCallback callback) {
+ if (VDBG) Log.v(TAG, "registerCallback:Service called");
+ if (mService == null) {
+ Log.e(TAG, "registerCallback:Service not available");
+ }
+
+ mCallbacks.add(callback);
+ }
+
+ /** API used to unreigester the wipower callbacks.
+ * {@hide}
+ */
+ public void unregisterCallback(WipowerManagerCallback callback) {
+ if (mService == null) {
+ Log.e(TAG, "Service not available");
+ }
+ mCallbacks.remove(callback);
+ }
+}
diff --git a/wipower-host/wipower_lib/android/wipower/WipowerManagerCallback.java b/wipower-host/wipower_lib/android/wipower/WipowerManagerCallback.java
new file mode 100644
index 0000000..fe871ed
--- /dev/null
+++ b/wipower-host/wipower_lib/android/wipower/WipowerManagerCallback.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package android.wipower;
+
+import android.wipower.WipowerManager.WipowerState;
+import android.wipower.WipowerManager.PowerApplyEvent;
+
+/**
+ * Application level callback for Wipower manager APIs.
+ *
+ * {@hide}
+ */
+public interface WipowerManagerCallback
+{
+
+ /**
+ * Clients should wait till onWipowerReady notification
+ * before initiating Wipower charging or using any other
+ * WipowerManager related APIs
+ * Clients should create the instance of WipowerManger and starts
+ * Wipower charging on onWipowerReady callback
+ * {@hide}
+ */
+ void onWipowerReady();
+
+ /**
+ * Indicates the Wipower state
+ *
+ * @param {@link WipowerState}
+ *
+ * {@hide}
+ */
+ void onWipowerStateChange(WipowerState state);
+
+ /**
+ * Indicates the Wipower Alert
+ *
+ * @param {@link alert}
+ *
+ * {@hide}
+ */
+ void onWipowerAlert(byte alert);
+
+ /**
+ * Indicates the Wipower PRU Data notifications
+ *
+ * @param {@link WipowerDynamicParam}
+ *
+ * {@hide}
+ */
+ void onWipowerData(WipowerDynamicParam value);
+
+ /**
+ * Indicates the power apply event
+ *
+ * @param {@link PowerApplyEvent}
+ *
+ * {@hide}
+ */
+ void onPowerApply(PowerApplyEvent event);
+
+}