19d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan/*
247f92c6507fa1bc0d0eef63fd649b81bfd36401fJim Tan * Copyright (C) 2017 The Android Open Source Project
39d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan *
447f92c6507fa1bc0d0eef63fd649b81bfd36401fJim Tan * Licensed under the Apache License, Version 2.0 (the "License");
547f92c6507fa1bc0d0eef63fd649b81bfd36401fJim Tan * you may not use this file except in compliance with the License.
647f92c6507fa1bc0d0eef63fd649b81bfd36401fJim Tan * You may obtain a copy of the License at
79d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan *
847f92c6507fa1bc0d0eef63fd649b81bfd36401fJim Tan *      http://www.apache.org/licenses/LICENSE-2.0
99d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan *
109d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan * Unless required by applicable law or agreed to in writing, software
1147f92c6507fa1bc0d0eef63fd649b81bfd36401fJim Tan * distributed under the License is distributed on an "AS IS" BASIS,
1247f92c6507fa1bc0d0eef63fd649b81bfd36401fJim Tan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1347f92c6507fa1bc0d0eef63fd649b81bfd36401fJim Tan * See the License for the specific language governing permissions and
1447f92c6507fa1bc0d0eef63fd649b81bfd36401fJim Tan * limitations under the License.
159d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan */
169d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
179d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanpackage com.android.pmc;
189d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
199d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.app.AlarmManager;
209d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.app.PendingIntent;
219d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.bluetooth.BluetoothAdapter;
229d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.bluetooth.le.BluetoothLeScanner;
239d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.bluetooth.le.ScanCallback;
249d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.bluetooth.le.ScanFilter;
259d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.bluetooth.le.ScanResult;
269d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.bluetooth.le.ScanSettings;
279d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.content.BroadcastReceiver;
289d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.content.Context;
299d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.content.Intent;
309d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.content.IntentFilter;
319d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.os.Bundle;
329d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.os.SystemClock;
339d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.util.Log;
349d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
359d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport java.util.ArrayList;
369d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport java.util.List;
379d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
389d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan/**
399d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan * Bluetooth LE Receiver functions for power testing.
409d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan */
419d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanpublic class BleScanReceiver extends BroadcastReceiver {
429d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    public static final String TAG = "BLEPOWER";
439d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    public static final String BLE_SCAN_INTENT = "com.android.pmc.BLESCAN";
449d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    public static final int START_SCAN = 1;
459d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    public static final int STOP_SCAN = 2;
469d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    public static final int INIT_ALARM_NO = 1;
479d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    private final Context mContext;
489d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    private final AlarmManager mAlarmManager;
499d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    private final BleScanListener mAlarmScanListener;
509d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    private BluetoothLeScanner mBleScanner;
519d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    private ScanSettings mScanSettings;
529d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    private List<ScanFilter> mScanFilterList;
53afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan    // Use PMCStatusLogger to send status and start & end times back to Python client
54afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan    private PMCStatusLogger mPMCStatusLogger;
55afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan    // Test start time is set when receiving the broadcast message from Python client
56afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan    private long mStartTestTime;
579d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
589d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    private ScanCallback mScanCallback = new ScanCallback() {
599d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        @Override
609d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        public void onScanResult(int callbackType, ScanResult result) {
619d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Log.e(TAG, "Bluetooth scan result: " + result.toString());
629d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        }
639d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
649d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        @Override
659d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        public void onScanFailed(int errorCode) {
669d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Log.e(TAG, "Scan Failed: " + errorCode);
679d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        }
689d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    };
699d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
709d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    /**
719d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     * Class to provide callback for AlarmManager to start BLE scan alarms
729d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     */
739d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    public class BleScanListener extends BroadcastReceiver {
749d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
759d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        public static final String BLESCAN =
769d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                       "com.android.pmc.BLESCAN.ALARM";
779d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
789d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        private int mScanTime;
799d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        private int mNoScanTime;
809d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        private int mNumAlarms;
81afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan        private int mFirstScanTime;
82afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan        private long mScanStartTime;
83afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan        private long mScanEndTime;
849d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
859d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        /**
869d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         * Constructor
879d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         *
889d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         */
899d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        public BleScanListener() {
903aad68c052667ec9b4c833f44432906359530da1Jim Tan            Log.d(TAG, "Start BleScanListener()");
919d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            BluetoothAdapter bleAdaptor = BluetoothAdapter.getDefaultAdapter();
92ca0b3497c93456c547da1b472d9e221ab8a13cbeJim Tan
939d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            if (bleAdaptor == null) {
94ca0b3497c93456c547da1b472d9e221ab8a13cbeJim Tan                Log.e(TAG, "BluetoothAdapter is Null");
959d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                return;
969d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            } else {
979d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                if (!bleAdaptor.isEnabled()) {
98ca0b3497c93456c547da1b472d9e221ab8a13cbeJim Tan                    Log.d(TAG, "BluetoothAdapter is NOT enabled, enable now");
99ca0b3497c93456c547da1b472d9e221ab8a13cbeJim Tan                    bleAdaptor.enable();
100ca0b3497c93456c547da1b472d9e221ab8a13cbeJim Tan                    if (!bleAdaptor.isEnabled()) {
101ca0b3497c93456c547da1b472d9e221ab8a13cbeJim Tan                        Log.e(TAG, "Can't enable Bluetooth");
102ca0b3497c93456c547da1b472d9e221ab8a13cbeJim Tan                        return;
103ca0b3497c93456c547da1b472d9e221ab8a13cbeJim Tan                    }
1049d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                }
1059d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
106ca0b3497c93456c547da1b472d9e221ab8a13cbeJim Tan
1079d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mBleScanner = bleAdaptor.getBluetoothLeScanner();
1089d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mScanFilterList = new ArrayList<ScanFilter>();
109150863588a257780ff2fda227518d793f03c2d87Andi Janti
110150863588a257780ff2fda227518d793f03c2d87Andi Janti            // Create ScanFilter object, to force scan even with screen OFF
111150863588a257780ff2fda227518d793f03c2d87Andi Janti            // using deviceName string of "dummy" for example
112150863588a257780ff2fda227518d793f03c2d87Andi Janti            ScanFilter scanFilterDeviceName = new ScanFilter.Builder().setDeviceName(
113150863588a257780ff2fda227518d793f03c2d87Andi Janti                       "dummy").build();
114150863588a257780ff2fda227518d793f03c2d87Andi Janti            // Add the object to FilterList
115150863588a257780ff2fda227518d793f03c2d87Andi Janti            mScanFilterList.add(scanFilterDeviceName);
116150863588a257780ff2fda227518d793f03c2d87Andi Janti
1173aad68c052667ec9b4c833f44432906359530da1Jim Tan            Log.d(TAG, "End BleScanListener()");
1189d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        }
1199d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
1209d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        /**
1219d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         * Function to be called by BleScanReceiver to start
1229d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         * Initial Bluetooth scan alarm
1239d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         *
1249d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         * @param scanMode - scan mode
1259d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         * @param startTime - time when the first scan needs to be started
1269d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         * @param scanTime - time for the scan is lasted
1279d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         * @param noScanTime - time when the scan is stopped
1289d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         * @param numAlarms - number of alarms to start and to stop scan
1299d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         *
1309d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         */
1319d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        public void firstAlarm(int scanMode, int startTime, int scanTime,
1329d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                               int noScanTime, int numAlarms) {
1339d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Log.d(TAG, "First Alarm for scan mode: " + scanMode);
1349d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mScanTime = scanTime;
1359d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mNoScanTime = noScanTime;
1369d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mNumAlarms = numAlarms;
137afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan            mFirstScanTime = startTime;
138afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan
1399d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mScanSettings = new ScanSettings.Builder().setScanMode(
1409d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                                            scanMode).build();
1419d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
1429d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Intent alarmIntent = new Intent(BleScanListener.BLESCAN);
1439d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            alarmIntent.putExtra("com.android.pmc.BLESCAN.Action", START_SCAN);
1449d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            alarmIntent.putExtra("com.android.pmc.BLESCAN.CurrentAlarm", INIT_ALARM_NO);
145afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan            long triggerTime = SystemClock.elapsedRealtime() + startTime * 1000;
1469d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mAlarmManager.setExactAndAllowWhileIdle(
1479d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                          AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime,
1489d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                          PendingIntent.getBroadcast(mContext, 0,
1499d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                                        alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT));
1509d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        }
1519d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
1529d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        /**
1539d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         * Function to be called by onReceive() to start subsequent alarm
1549d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         *
1559d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         * @param intent - intent to get extra data
1569d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         * @param timeInterval - time for alarm to trigger next alarm
1579d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         * @param nextAction - next action for the alarm
1589d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         *
1599d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         */
1609d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        public void repeatAlarm(Intent intent, int timeInterval,
1619d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                                  int nextAction) {
1629d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
1639d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            int currentAlarm = intent.getIntExtra("com.android.pmc.BLESCAN.CurrentAlarm", 0);
1649d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Log.d(TAG, "repeatAlarm() currentAlarm: " + currentAlarm);
1659d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            if (currentAlarm == 0) {
1669d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.d(TAG, "Received Alarm with no currentAlarm");
1679d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                return;
1689d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
1699d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            if (currentAlarm >= mNumAlarms) {
170afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan                mPMCStatusLogger.flash();  // To flash out timestamps into log file
1719d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.d(TAG, "All alarms are done");
1729d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                return;
1739d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
1749d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Log.d(TAG, "Next Action: " + nextAction);
1759d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Intent alarmIntent = new Intent(BleScanListener.BLESCAN);
1769d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            alarmIntent.putExtra("com.android.pmc.BLESCAN.Action", nextAction);
1779d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            alarmIntent.putExtra("com.android.pmc.BLESCAN.CurrentAlarm", ++currentAlarm);
1789d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            long triggerTime = SystemClock.elapsedRealtime()
1799d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                                          + timeInterval * 1000;
1809d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mAlarmManager.setExactAndAllowWhileIdle(
1819d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                          AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerTime,
1829d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                          PendingIntent.getBroadcast(mContext, 0,
1839d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                          alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT));
1849d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        }
1859d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
1869d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        /**
1879d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         * Callback will be called for AlarmManager to start Bluetooth LE scan
1889d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         *
1899d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         * @param context - system will provide a context to this function
1909d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         * @param intent - system will provide an intent to this function
1919d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan         */
1929d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        @Override
1939d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        public void onReceive(Context context, Intent intent) {
1949d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            if (!intent.getAction().equals(BLESCAN)) {
1959d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                return;
1969d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
1979d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            int action = intent.getIntExtra("com.android.pmc.BLESCAN.Action", 0);
1989d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Log.d(TAG, "onReceive() Action: " + action);
1999d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            if (action == -1) {
2009d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.e(TAG, "Received Alarm with no Action");
2019d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                return;
2029d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
2039d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            if (action == START_SCAN) {
2049d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.v(TAG, "Before Start Scan");
205afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan                mScanStartTime = System.currentTimeMillis();
2069d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                mBleScanner.startScan(mScanFilterList, mScanSettings,
2079d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                                 mScanCallback);
2089d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                repeatAlarm(intent, mScanTime, STOP_SCAN);
2099d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            } else if (action == STOP_SCAN) {
2109d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.v(TAG, "Before Stop scan");
211afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan                mScanEndTime = System.currentTimeMillis();
212afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan                mPMCStatusLogger.logAlarmTimes(mScanStartTime / 1000.0, mScanEndTime / 1000.0);
2139d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                mBleScanner.stopScan(mScanCallback);
214afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan                if ((mScanEndTime - mStartTestTime)
215afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan                        < ((mScanTime + mNoScanTime) * mNumAlarms / 2 + mFirstScanTime) * 1000) {
216afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan                    repeatAlarm(intent, mNoScanTime, START_SCAN);
217afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan                } else {
218afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan                    mPMCStatusLogger.flash();  // To flash out timestamps into log file
219afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan                    Log.d(TAG, "Time is up to end");
220afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan                }
2219d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            } else {
2229d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.e(TAG, "Unknown Action");
2239d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
2249d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        }
2259d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    }
2269d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
2279d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    /**
2289d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     * Constructor to be called by PMC
2299d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     *
2309d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     * @param context - PMC will provide a context
2319d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     * @param alarmManager - PMC will provide alarmManager
2329d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     */
2339d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    public BleScanReceiver(Context context, AlarmManager alarmManager) {
2349d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        // prepare for setting alarm service
2359d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        mContext = context;
2369d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        mAlarmManager = alarmManager;
2379d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        mAlarmScanListener = new BleScanListener();
2389d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
23947f92c6507fa1bc0d0eef63fd649b81bfd36401fJim Tan        // RegisterAlarmReceiver for BleScanListener
2409d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        mContext.registerReceiver(mAlarmScanListener,
2419d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                new IntentFilter(BleScanListener.BLESCAN));
2429d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
2439d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    }
2449d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
2459d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    /**
2469d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     * Method to receive the broadcast from python client
2479d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     *
2489d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     * @param context - system will provide a context to this function
2499d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     * @param intent - system will provide an intent to this function
2509d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     */
2519d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    @Override
2529d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    public void onReceive(Context context, Intent intent) {
2539d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        if (intent.getAction().equals(BLE_SCAN_INTENT)) {
2549d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Bundle extras = intent.getExtras();
2559d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            int scanMode = -1, startTime = 0, scanTime = 0, noScanTime = 0;
2569d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            int repetitions = 1;
2579d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            String str;
2589d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
259afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan            mStartTestTime = System.currentTimeMillis();
260afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan            mPMCStatusLogger = new PMCStatusLogger(TAG + ".log", TAG);
261afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan
2629d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            if (extras == null) {
2639d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.e(TAG, "No parameters specified");
2649d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                return;
2659d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
2669d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
2679d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            if (!extras.containsKey("ScanMode")) {
2689d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.e(TAG, "No scan mode specified");
2699d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                return;
2709d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
2719d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            str = extras.getString("ScanMode");
2729d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Log.d(TAG, "Scan Mode = " + str);
2739d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            scanMode = Integer.valueOf(str);
2749d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
2759d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            if (!extras.containsKey("StartTime")) {
2769d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.e(TAG, "No Start Time specified");
2779d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                return;
2789d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
2799d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            str = extras.getString("StartTime");
2809d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Log.d(TAG, "Start Time = " + str);
2819d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            startTime = Integer.valueOf(str);
2829d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
2839d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            if (!extras.containsKey("ScanTime")) {
2849d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.e(TAG, "No Scan Time specified");
2859d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                return;
2869d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
2879d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            str = extras.getString("ScanTime");
2889d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Log.d(TAG, "Scan Time = " + str);
2899d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            scanTime = Integer.valueOf(str);
2909d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
2919d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            if (extras.containsKey("Repetitions")) {
2929d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
2939d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                str = extras.getString("Repetitions");
2949d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.d(TAG, "Repetitions = " + str);
2959d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                repetitions = Integer.valueOf(str);
2969d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
2979d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                if (!extras.containsKey("NoScanTime")) {
2989d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                    Log.e(TAG, "No NoScan Time specified");
2999d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                    return;
3009d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                }
3019d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                str = extras.getString("NoScanTime");
3029d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.d(TAG, "NoScan Time = " + str);
3039d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                noScanTime = Integer.valueOf(str);
3049d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
3059d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            if (scanTime == 0 || startTime == 0 || scanMode == -1) {
3069d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.d(TAG, "Invalid paramters");
3079d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                return;
3089d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
3099d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mAlarmScanListener.firstAlarm(scanMode, startTime,
3109d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                                       scanTime, noScanTime, repetitions * 2);
311afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan            if (mBleScanner != null && mScanFilterList != null && mScanSettings != null
312afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan                                 && mScanCallback != null) {
313afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan                mPMCStatusLogger.logStatus("READY");
314afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan            } else {
315afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan                Log.e(TAG, "BLE scanner is not ready to start test");
316afd0ad43555fda4808de6e9dc35717a0fe11fcbaJim Tan            }
3179d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        }
3189d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    }
3199d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan}
320