tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CocoaSensor.mm (4301B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 #include "Hal.h"
      5 #include "nsITimer.h"
      6 #include "smslib.h"
      7 #include "nsComponentManagerUtils.h"
      8 
      9 #include <mach/mach.h>
     10 #include <cmath>
     11 #import <IOKit/IOKitLib.h>
     12 
     13 #define MEAN_GRAVITY 9.80665
     14 #define DEFAULT_SENSOR_POLL 100
     15 using namespace mozilla::hal;
     16 namespace mozilla {
     17 namespace hal_impl {
     18 static nsITimer* sUpdateTimer = nullptr;
     19 static bool sActiveSensors[NUM_SENSOR_TYPE];
     20 static io_connect_t sDataPort = IO_OBJECT_NULL;
     21 static uint64_t sLastMean = -1;
     22 static float LMUvalueToLux(uint64_t aValue) {
     23  // Conversion formula from regression. See Bug 793728.
     24  // -3*(10^-27)*x^4 + 2.6*(10^-19)*x^3 + -3.4*(10^-12)*x^2 + 3.9*(10^-5)*x -
     25  // 0.19
     26  long double powerC4 = 1 / pow((long double)10, 27);
     27  long double powerC3 = 1 / pow((long double)10, 19);
     28  long double powerC2 = 1 / pow((long double)10, 12);
     29  long double powerC1 = 1 / pow((long double)10, 5);
     30 
     31  long double term4 = -3.0 * powerC4 * pow(aValue, 4);
     32  long double term3 = 2.6 * powerC3 * pow(aValue, 3);
     33  long double term2 = -3.4 * powerC2 * pow(aValue, 2);
     34  long double term1 = 3.9 * powerC1 * aValue;
     35 
     36  float lux = ceil(static_cast<float>(term4 + term3 + term2 + term1 - 0.19));
     37  return lux > 0 ? lux : 0;
     38 }
     39 void UpdateHandler(nsITimer* aTimer, void* aClosure) {
     40  for (int i = 0; i < NUM_SENSOR_TYPE; i++) {
     41    if (!sActiveSensors[i]) {
     42      continue;
     43    }
     44    SensorType sensor = static_cast<SensorType>(i);
     45    nsTArray<float> values;
     46    if (sensor == SENSOR_ACCELERATION) {
     47      sms_acceleration accel;
     48      smsGetData(&accel);
     49 
     50      values.AppendElement(accel.x * MEAN_GRAVITY);
     51      values.AppendElement(accel.y * MEAN_GRAVITY);
     52      values.AppendElement(accel.z * MEAN_GRAVITY);
     53    } else if (sensor == SENSOR_LIGHT && sDataPort != IO_OBJECT_NULL) {
     54      kern_return_t kr;
     55      uint32_t outputs = 2;
     56      uint64_t lightLMU[outputs];
     57 
     58      kr = IOConnectCallMethod(sDataPort, 0, nil, 0, nil, 0, lightLMU, &outputs,
     59                               nil, 0);
     60      if (kr == KERN_SUCCESS) {
     61        uint64_t mean = (lightLMU[0] + lightLMU[1]) / 2;
     62        if (mean == sLastMean) {
     63          continue;
     64        }
     65        sLastMean = mean;
     66        values.AppendElement(LMUvalueToLux(mean));
     67      } else if (kr == kIOReturnBusy) {
     68        continue;
     69      }
     70    }
     71 
     72    hal::SensorData sdata(sensor, PR_Now(), values);
     73    hal::NotifySensorChange(sdata);
     74  }
     75 }
     76 void EnableSensorNotifications(SensorType aSensor) {
     77  if (aSensor == SENSOR_ACCELERATION) {
     78    int result = smsStartup(nil, nil);
     79 
     80    if (result != SMS_SUCCESS) {
     81      return;
     82    }
     83 
     84    if (!smsLoadCalibration()) {
     85      return;
     86    }
     87  } else if (aSensor == SENSOR_LIGHT) {
     88    io_service_t serviceObject;
     89    serviceObject = IOServiceGetMatchingService(
     90        kIOMasterPortDefault, IOServiceMatching("AppleLMUController"));
     91    if (!serviceObject) {
     92      return;
     93    }
     94    kern_return_t kr;
     95    kr = IOServiceOpen(serviceObject, mach_task_self(), 0, &sDataPort);
     96    IOObjectRelease(serviceObject);
     97    if (kr != KERN_SUCCESS) {
     98      return;
     99    }
    100  } else {
    101    NS_WARNING("EnableSensorNotifications called on an unknown sensor type");
    102    return;
    103  }
    104  sActiveSensors[aSensor] = true;
    105 
    106  if (!sUpdateTimer) {
    107    CallCreateInstance("@mozilla.org/timer;1", &sUpdateTimer);
    108    if (sUpdateTimer) {
    109      sUpdateTimer->InitWithNamedFuncCallback(
    110          UpdateHandler, nullptr, DEFAULT_SENSOR_POLL,
    111          nsITimer::TYPE_REPEATING_SLACK, "hal_impl::UpdateHandler"_ns);
    112    }
    113  }
    114 }
    115 void DisableSensorNotifications(SensorType aSensor) {
    116  if (!sActiveSensors[aSensor] ||
    117      (aSensor != SENSOR_ACCELERATION && aSensor != SENSOR_LIGHT)) {
    118    return;
    119  }
    120 
    121  sActiveSensors[aSensor] = false;
    122 
    123  if (aSensor == SENSOR_ACCELERATION) {
    124    smsShutdown();
    125  } else if (aSensor == SENSOR_LIGHT) {
    126    IOServiceClose(sDataPort);
    127  }
    128  // If all sensors are disabled, cancel the update timer.
    129  if (sUpdateTimer) {
    130    for (int i = 0; i < NUM_SENSOR_TYPE; i++) {
    131      if (sActiveSensors[i]) {
    132        return;
    133      }
    134    }
    135    sUpdateTimer->Cancel();
    136    NS_RELEASE(sUpdateTimer);
    137  }
    138 }
    139 }  // namespace hal_impl
    140 }  // namespace mozilla