static bool startScan( void (*pfnOnResultsAvailable)(wifi_request_id, unsigned),
                       int max_ap_per_scan, int base_period, int report_threshold) {

    /* Get capabilties */
    wifi_gscan_capabilities capabilities;
    int result = wifi_get_gscan_capabilities(wlan0Handle, &capabilities);
    if (result < 0) {
        printMsg("failed to get scan capabilities - %d\n", result);
        printMsg("trying scan anyway ..\n");
    } else {
        printScanCapabilities(capabilities);
    }

    wifi_scan_cmd_params params;
    memset(&params, 0, sizeof(params));

    if(num_channels > 0){
        params.max_ap_per_scan = max_ap_per_scan;
        params.base_period = base_period;                      // 5 second by default
        params.report_threshold = report_threshold;
        params.num_buckets = 1;

        params.buckets[0].bucket = 0;
        params.buckets[0].band = WIFI_BAND_UNSPECIFIED;
        params.buckets[0].period = base_period;
        params.buckets[0].num_channels = num_channels;

        for(int i = 0; i < num_channels; i++){
            params.buckets[0].channels[i].channel = channel_list[i];
        }

    } else {

        /* create a schedule to scan channels 1, 6, 11 every 5 second and
         * scan 36, 40, 44, 149, 153, 157, 161 165 every 10 second */

      params.max_ap_per_scan = max_ap_per_scan;
      params.base_period = base_period;                      // 5 second
      params.report_threshold = report_threshold;
      params.num_buckets = 3;

      params.buckets[0].bucket = 0;
      params.buckets[0].band = WIFI_BAND_UNSPECIFIED;
      params.buckets[0].period = 5000;                // 5 second
      params.buckets[0].report_events = 0;
      params.buckets[0].num_channels = 2;

      params.buckets[0].channels[0].channel = 2412;
      params.buckets[0].channels[1].channel = 2437;

      params.buckets[1].bucket = 1;
      params.buckets[1].band = WIFI_BAND_A;
      params.buckets[1].period = 10000;               // 10 second
      params.buckets[1].report_events = 1;
      params.buckets[1].num_channels = 8;   // driver should ignore list since band is specified


      params.buckets[1].channels[0].channel = 5180;
      params.buckets[1].channels[1].channel = 5200;
      params.buckets[1].channels[2].channel = 5220;
      params.buckets[1].channels[3].channel = 5745;
      params.buckets[1].channels[4].channel = 5765;
      params.buckets[1].channels[5].channel = 5785;
      params.buckets[1].channels[6].channel = 5805;
      params.buckets[1].channels[7].channel = 5825;

      params.buckets[2].bucket = 2;
      params.buckets[2].band = WIFI_BAND_UNSPECIFIED;
      params.buckets[2].period = 15000;                // 15 second
      params.buckets[2].report_events = 2;
      params.buckets[2].num_channels = 1;

      params.buckets[2].channels[0].channel = 2462;

    }

    wifi_scan_result_handler handler;
    memset(&handler, 0, sizeof(handler));
    handler.on_scan_results_available = pfnOnResultsAvailable;
    handler.on_scan_event = on_scan_event;

    scanCmdId = getNewCmdId();
    printMsg("Starting scan --->\n");
    return wifi_start_gscan(scanCmdId, wlan0Handle, params, handler) == WIFI_SUCCESS;
}
static int scanOnce(wifi_band band, wifi_scan_result *results, int num_results) {

    saved_scan_results = results;
    max_saved_scan_results = num_results;
    num_saved_scan_results = 0;

    wifi_scan_cmd_params params;
    memset(&params, 0, sizeof(params));

    params.max_ap_per_scan = 10;
    params.base_period = 5000;                        // 5 second by default
    params.report_threshold = 90;
    params.num_buckets = 1;

    params.buckets[0].bucket = 0;
    params.buckets[0].band = band;
    params.buckets[0].period = 5000;                  // 5 second
    params.buckets[0].report_events = 2;              // REPORT_EVENTS_AFTER_EACH_SCAN
    params.buckets[0].num_channels = 0;

    wifi_scan_result_handler handler;
    memset(&handler, 0, sizeof(handler));
    handler.on_scan_results_available = NULL;
    handler.on_scan_event = on_single_shot_scan_event;
    handler.on_full_scan_result = on_full_scan_result;

    int scanCmdId = getNewCmdId();
    printMsg("Starting scan --->\n");
    if (wifi_start_gscan(scanCmdId, wlan0Handle, params, handler) == WIFI_SUCCESS) {
        int events = 0;
        while (true) {
            EventInfo info;
            memset(&info, 0, sizeof(info));
            getEventFromCache(info);
            if (info.type == EVENT_TYPE_SCAN_RESULTS_AVAILABLE
                || info.type == EVENT_TYPE_SCAN_COMPLETE) {
                int retrieved_num_results = num_saved_scan_results;
                if (retrieved_num_results == 0) {
                    printMsg("fetched 0 scan results, waiting for more..\n");
                    continue;
                } else {
                    printMsg("fetched %d scan results\n", retrieved_num_results);

                    /*
                    printScanHeader();

                    for (int i = 0; i < retrieved_num_results; i++) {
                        printScanResult(results[i]);
                    }
                    */

                    printMsg("Scan once completed, stopping scan\n");
                    wifi_stop_gscan(scanCmdId, wlan0Handle);
                    saved_scan_results = NULL;
                    max_saved_scan_results = 0;
                    num_saved_scan_results = 0;
                    return retrieved_num_results;
                }
            }
        }
    } else {
        return 0;
    }
}
static jboolean android_net_wifi_startScan(
        JNIEnv *env, jclass cls, jint iface, jint id, jobject settings) {

    wifi_interface_handle handle = getIfaceHandle(env, cls, iface);
    ALOGD("starting scan on interface[%d] = %p", iface, handle);

    wifi_scan_cmd_params params;
    memset(&params, 0, sizeof(params));

    params.base_period = getIntField(env, settings, "base_period_ms");
    params.max_ap_per_scan = getIntField(env, settings, "max_ap_per_scan");
    params.report_threshold = getIntField(env, settings, "report_threshold");

    ALOGD("Initialized common fields %d, %d, %d", params.base_period,
            params.max_ap_per_scan, params.report_threshold);

    const char *bucket_array_type = "[Lcom/android/server/wifi/WifiNative$BucketSettings;";
    const char *channel_array_type = "[Lcom/android/server/wifi/WifiNative$ChannelSettings;";

    jobjectArray buckets = (jobjectArray)getObjectField(env, settings, "buckets", bucket_array_type);
    params.num_buckets = getIntField(env, settings, "num_buckets");

    ALOGD("Initialized num_buckets to %d", params.num_buckets);

    for (int i = 0; i < params.num_buckets; i++) {
        jobject bucket = getObjectArrayField(env, settings, "buckets", bucket_array_type, i);

        params.buckets[i].bucket = getIntField(env, bucket, "bucket");
        params.buckets[i].band = (wifi_band) getIntField(env, bucket, "band");
        params.buckets[i].period = getIntField(env, bucket, "period_ms");

        ALOGD("Initialized common bucket fields %d:%d:%d", params.buckets[i].bucket,
                params.buckets[i].band, params.buckets[i].period);

        int report_events = getIntField(env, bucket, "report_events");
        params.buckets[i].report_events = report_events;

        ALOGD("Initialized report events to %d", params.buckets[i].report_events);

        jobjectArray channels = (jobjectArray)getObjectField(
                env, bucket, "channels", channel_array_type);

        params.buckets[i].num_channels = getIntField(env, bucket, "num_channels");
        ALOGD("Initialized num_channels to %d", params.buckets[i].num_channels);

        for (int j = 0; j < params.buckets[i].num_channels; j++) {
            jobject channel = getObjectArrayField(env, bucket, "channels", channel_array_type, j);

            params.buckets[i].channels[j].channel = getIntField(env, channel, "frequency");
            params.buckets[i].channels[j].dwellTimeMs = getIntField(env, channel, "dwell_time_ms");

            bool passive = getBoolField(env, channel, "passive");
            params.buckets[i].channels[j].passive = (passive ? 1 : 0);

            ALOGD("Initialized channel %d", params.buckets[i].channels[j].channel);
        }
    }

    ALOGD("Initialized all fields");

    wifi_scan_result_handler handler;
    memset(&handler, 0, sizeof(handler));
    handler.on_scan_results_available = &onScanResultsAvailable;
    handler.on_full_scan_result = &onFullScanResult;
    handler.on_scan_event = &onScanEvent;

    return wifi_start_gscan(id, handle, params, handler) == WIFI_SUCCESS;
}