openpilot v0.6 release

old-commit-hash: 8a9ed94f5f
commatwo_master
Vehicle Researcher 6 years ago
parent 5446b30185
commit 9abcfabc5f
  1. 1
      .gitignore
  2. 32
      Dockerfile.openpilot
  3. 3
      Pipfile
  4. 3
      Pipfile.lock
  5. 6
      README.md
  6. 13
      RELEASES.md
  7. 2
      apk/ai.comma.plus.black.apk
  8. 4
      apk/ai.comma.plus.frame.apk
  9. 4
      apk/ai.comma.plus.offroad.apk
  10. 2
      common/fingerprints.py
  11. 2
      common/kalman/Makefile
  12. 1
      common/params.py
  13. 7
      common/realtime.py
  14. 7
      common/transformations/camera.py
  15. 88
      installer/updater/Makefile
  16. 7
      installer/updater/update.json
  17. 4
      installer/updater/updater
  18. 675
      installer/updater/updater.cc
  19. 6
      launch_chffrplus.sh
  20. 4
      models/driving_model.dlc
  21. 3
      phonelibs/android_frameworks_native/get.txt
  22. 3
      phonelibs/android_frameworks_native/include/android/asset_manager.h
  23. 3
      phonelibs/android_frameworks_native/include/android/asset_manager_jni.h
  24. 3
      phonelibs/android_frameworks_native/include/android/bitmap.h
  25. 3
      phonelibs/android_frameworks_native/include/android/configuration.h
  26. 3
      phonelibs/android_frameworks_native/include/android/input.h
  27. 3
      phonelibs/android_frameworks_native/include/android/keycodes.h
  28. 3
      phonelibs/android_frameworks_native/include/android/looper.h
  29. 3
      phonelibs/android_frameworks_native/include/android/multinetwork.h
  30. 3
      phonelibs/android_frameworks_native/include/android/native_activity.h
  31. 3
      phonelibs/android_frameworks_native/include/android/native_window.h
  32. 3
      phonelibs/android_frameworks_native/include/android/native_window_jni.h
  33. 3
      phonelibs/android_frameworks_native/include/android/obb.h
  34. 3
      phonelibs/android_frameworks_native/include/android/rect.h
  35. 3
      phonelibs/android_frameworks_native/include/android/sensor.h
  36. 3
      phonelibs/android_frameworks_native/include/android/storage_manager.h
  37. 3
      phonelibs/android_frameworks_native/include/android/trace.h
  38. 3
      phonelibs/android_frameworks_native/include/android/window.h
  39. 3
      phonelibs/android_frameworks_native/include/batteryservice/BatteryService.h
  40. 3
      phonelibs/android_frameworks_native/include/batteryservice/IBatteryPropertiesListener.h
  41. 3
      phonelibs/android_frameworks_native/include/batteryservice/IBatteryPropertiesRegistrar.h
  42. 3
      phonelibs/android_frameworks_native/include/binder/AppOpsManager.h
  43. 3
      phonelibs/android_frameworks_native/include/binder/Binder.h
  44. 3
      phonelibs/android_frameworks_native/include/binder/BinderService.h
  45. 3
      phonelibs/android_frameworks_native/include/binder/BpBinder.h
  46. 3
      phonelibs/android_frameworks_native/include/binder/BufferedTextOutput.h
  47. 3
      phonelibs/android_frameworks_native/include/binder/Debug.h
  48. 3
      phonelibs/android_frameworks_native/include/binder/IAppOpsCallback.h
  49. 3
      phonelibs/android_frameworks_native/include/binder/IAppOpsService.h
  50. 3
      phonelibs/android_frameworks_native/include/binder/IBatteryStats.h
  51. 3
      phonelibs/android_frameworks_native/include/binder/IBinder.h
  52. 3
      phonelibs/android_frameworks_native/include/binder/IInterface.h
  53. 3
      phonelibs/android_frameworks_native/include/binder/IMemory.h
  54. 3
      phonelibs/android_frameworks_native/include/binder/IPCThreadState.h
  55. 3
      phonelibs/android_frameworks_native/include/binder/IPermissionController.h
  56. 3
      phonelibs/android_frameworks_native/include/binder/IProcessInfoService.h
  57. 3
      phonelibs/android_frameworks_native/include/binder/IServiceManager.h
  58. 3
      phonelibs/android_frameworks_native/include/binder/MemoryBase.h
  59. 3
      phonelibs/android_frameworks_native/include/binder/MemoryDealer.h
  60. 3
      phonelibs/android_frameworks_native/include/binder/MemoryHeapBase.h
  61. 3
      phonelibs/android_frameworks_native/include/binder/MemoryHeapIon.h
  62. 3
      phonelibs/android_frameworks_native/include/binder/Parcel.h
  63. 3
      phonelibs/android_frameworks_native/include/binder/PermissionCache.h
  64. 3
      phonelibs/android_frameworks_native/include/binder/ProcessInfoService.h
  65. 3
      phonelibs/android_frameworks_native/include/binder/ProcessState.h
  66. 3
      phonelibs/android_frameworks_native/include/binder/TextOutput.h
  67. 3
      phonelibs/android_frameworks_native/include/diskusage/dirsize.h
  68. 3
      phonelibs/android_frameworks_native/include/gui/BitTube.h
  69. 3
      phonelibs/android_frameworks_native/include/gui/BufferItem.h
  70. 3
      phonelibs/android_frameworks_native/include/gui/BufferItemConsumer.h
  71. 3
      phonelibs/android_frameworks_native/include/gui/BufferQueue.h
  72. 3
      phonelibs/android_frameworks_native/include/gui/BufferQueueConsumer.h
  73. 3
      phonelibs/android_frameworks_native/include/gui/BufferQueueCore.h
  74. 3
      phonelibs/android_frameworks_native/include/gui/BufferQueueDefs.h
  75. 3
      phonelibs/android_frameworks_native/include/gui/BufferQueueProducer.h
  76. 3
      phonelibs/android_frameworks_native/include/gui/BufferSlot.h
  77. 3
      phonelibs/android_frameworks_native/include/gui/ConsumerBase.h
  78. 3
      phonelibs/android_frameworks_native/include/gui/CpuConsumer.h
  79. 3
      phonelibs/android_frameworks_native/include/gui/DisplayEventReceiver.h
  80. 3
      phonelibs/android_frameworks_native/include/gui/GLConsumer.h
  81. 3
      phonelibs/android_frameworks_native/include/gui/GraphicBufferAlloc.h
  82. 3
      phonelibs/android_frameworks_native/include/gui/GuiConfig.h
  83. 3
      phonelibs/android_frameworks_native/include/gui/IConsumerListener.h
  84. 3
      phonelibs/android_frameworks_native/include/gui/IDisplayEventConnection.h
  85. 3
      phonelibs/android_frameworks_native/include/gui/IGraphicBufferAlloc.h
  86. 3
      phonelibs/android_frameworks_native/include/gui/IGraphicBufferConsumer.h
  87. 3
      phonelibs/android_frameworks_native/include/gui/IGraphicBufferProducer.h
  88. 4
      phonelibs/android_frameworks_native/include/gui/IProducerListener.h
  89. 3
      phonelibs/android_frameworks_native/include/gui/ISensorEventConnection.h
  90. 3
      phonelibs/android_frameworks_native/include/gui/ISensorServer.h
  91. 3
      phonelibs/android_frameworks_native/include/gui/ISurfaceComposer.h
  92. 3
      phonelibs/android_frameworks_native/include/gui/ISurfaceComposerClient.h
  93. 3
      phonelibs/android_frameworks_native/include/gui/Sensor.h
  94. 3
      phonelibs/android_frameworks_native/include/gui/SensorEventQueue.h
  95. 3
      phonelibs/android_frameworks_native/include/gui/SensorManager.h
  96. 3
      phonelibs/android_frameworks_native/include/gui/StreamSplitter.h
  97. 3
      phonelibs/android_frameworks_native/include/gui/Surface.h
  98. 3
      phonelibs/android_frameworks_native/include/gui/SurfaceComposerClient.h
  99. 3
      phonelibs/android_frameworks_native/include/gui/SurfaceControl.h
  100. 3
      phonelibs/android_frameworks_native/include/input/IInputFlinger.h
  101. Some files were not shown because too many files have changed in this diff Show More

1
.gitignore vendored

@ -1,3 +1,4 @@
venv/
.DS_Store
.tags
.ipynb_checkpoints

@ -4,32 +4,44 @@ ENV PYTHONUNBUFFERED 1
RUN apt-get update && apt-get install -y \
autoconf \
build-essential \
clang \
wget \
bzip2 \
clang \
git \
libarchive-dev \
libavcodec-dev \
libavdevice-dev \
libavfilter-dev \
libavresample-dev \
libavutil-dev \
libffi-dev \
libglib2.0-0 \
libssl-dev \
libswscale-dev \
libtool \
python-pip \
libzmq5-dev \
libffi-dev \
libusb-1.0-0 \
libssl-dev \
libzmq5-dev \
ocl-icd-libopencl1 \
ocl-icd-opencl-dev \
opencl-headers
opencl-headers \
pkg-config \
python-pip \
wget
COPY phonelibs/install_capnp.sh /tmp/install_capnp.sh
RUN /tmp/install_capnp.sh
RUN pip install --upgrade pip==18.0
RUN pip install numpy==1.11.2 scipy==0.18.1 matplotlib==2.1.2
RUN pip install pipenv==2018.11.26
COPY requirements_openpilot.txt /tmp/
RUN pip install -r /tmp/requirements_openpilot.txt
COPY Pipfile /tmp/
COPY Pipfile.lock /tmp/
RUN cd /tmp && pipenv install --deploy --system
ENV PYTHONPATH /tmp/openpilot:$PYTHONPATH
RUN git clone --branch v0.6 https://github.com/commaai/openpilot-tools.git /tmp/openpilot/tools
RUN pip install -r /tmp/openpilot/tools/requirements.txt
COPY ./.pylintrc /tmp/openpilot/.pylintrc
COPY ./common /tmp/openpilot/common
COPY ./cereal /tmp/openpilot/cereal

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c8eab0ec610fccd29115e8451f1088ed71db5ce7575956d08fd76baf62172e28
size 2565

3
Pipfile.lock generated

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:14e21ae221670a6b9178371274d1b30428f6d136195e8320943e8988764d9bd4
size 152571

@ -1,4 +1,4 @@
[![](https://i.imgur.com/xY2gdHv.png)](#)
[![](https://i.imgur.com/UetIFyH.jpg)](#)
Welcome to openpilot
======
@ -91,13 +91,15 @@ Supported Cars
| Kia | Optima 2019 | SCC + LKAS | Yes | Stock | 0mph | 0mph | Custom<sup>6</sup>|
| Kia | Sorento 2018 | All | Yes | Stock | 0mph | 0mph | Custom<sup>6</sup>|
| Kia | Stinger 2018 | SCC + LKAS | Yes | Stock | 0mph | 0mph | Custom<sup>6</sup>|
| Lexus | ES Hybrid 2019 | All | Yes | Yes | 0mph | 0mph | Toyota |
| Lexus | RX Hybrid 2016-19 | All | Yes | Yes<sup>2</sup>| 0mph | 0mph | Toyota |
| Subaru | Crosstrek 2018 | EyeSight | Yes | Stock | 0mph | 0mph | Custom<sup>4</sup>|
| Subaru | Impreza 2019 | EyeSight | Yes | Stock | 0mph | 0mph | Custom<sup>4</sup>|
| Toyota | Avalon 2016 | TSS-P | Yes | Yes<sup>2</sup>| 20mph<sup>1</sup>| 0mph | Toyota |
| Toyota | Camry 2018 | All | Yes | Stock | 0mph<sup>5</sup> | 0mph | Toyota |
| Toyota | C-HR 2017-18 | All | Yes | Stock | 0mph | 0mph | Toyota |
| Toyota | Corolla 2017-18 | All | Yes | Yes<sup>2</sup>| 20mph<sup>1</sup>| 0mph | Toyota |
| Toyota | Corolla 2017-19 | All | Yes | Yes<sup>2</sup>| 20mph<sup>1</sup>| 0mph | Toyota |
| Toyota | Corolla 2020 | All | Yes | Yes | 0mph | 0mph | Toyota |
| Toyota | Corolla Hatchback 2019 | All | Yes | Yes | 0mph | 0mph | Toyota |
| Toyota | Highlander 2017-18 | All | Yes | Yes<sup>2</sup>| 0mph | 0mph | Toyota |
| Toyota | Highlander Hybrid 2018 | All | Yes | Yes<sup>2</sup>| 0mph | 0mph | Toyota |

@ -1,3 +1,16 @@
Version 0.6 (2019-07-01)
========================
* New model, with double the pixels and ten times the temporal context!
* Car should not take exits when in the right lane
* openpilot uses only ~65% of the CPU (down from 75%)
* Routes visible in connect/explorer after only 0.2% is uploaded (qlogs)
* loggerd and sensord are open source, every line of openpilot is now open
* Panda safety code is MISRA compliant and ships with a signed version on release2
* New NEOS is 500MB smaller and has a reproducible usr/pipenv
* Lexus ES Hybrid support thanks to wocsor!
* Improve tuning for supported Toyota with TSS2
* Various other stability improvements
Version 0.5.13 (2019-05-31)
==========================
* Reduce panda power consumption by 70%, down to 80mW, when car is off (not for GM)

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6e6f3a8037283b87271a7bb0c95a9ae1a8ff5a86dea7e2b25d49911179b6e05e
oid sha256:309b46b7c38f10da52b18b0340eb3c57b633558a9a27c3ca4116474969ebb456
size 84675

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:61fc21ef8cec4ca15be05b1b5fdb9c4d95f3a78be891a36d84bd2dd89441e28e
size 2596571
oid sha256:2b53c6b8927e634d09ece8c780cf8f3d4201a6ea1c8327396a46b663da0e94a6
size 2604116

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6976978d140b928a499f26a6e8d879a752034a762154dde2d9bde55ef59a9c29
size 18310604
oid sha256:3eaf6c7d0666f721967fdf5441ea254568cbe898ee71f31e55e41c0cdd6cc41b
size 18310731

@ -4,7 +4,7 @@ from common.basedir import BASEDIR
def get_fingerprint_list():
# read all the folders in selfdrive/car and return a dict where:
# - keys are all the car models for which we have a fingerprint
# - values are lists dicts of messages that constitute the unique
# - values are lists dicts of messages that constitute the unique
# CAN fingerprint of each car model and all its variants
fingerprints = {}
for car_folder in [x[0] for x in os.walk(BASEDIR + '/selfdrive/car')]:

@ -1,7 +1,7 @@
all: simple_kalman_impl.so
simple_kalman_impl.so: simple_kalman_impl.pyx simple_kalman_impl.pxd simple_kalman_setup.py
python simple_kalman_setup.py build_ext --inplace
python2 simple_kalman_setup.py build_ext --inplace
rm -rf build
rm simple_kalman_impl.c

@ -65,6 +65,7 @@ keys = {
"IsGeofenceEnabled": [TxType.PERSISTENT],
"IsMetric": [TxType.PERSISTENT],
"IsUpdateAvailable": [TxType.PERSISTENT],
"IsUploadRawEnabled": [TxType.PERSISTENT],
"IsUploadVideoOverCellularEnabled": [TxType.PERSISTENT],
"LimitSetSpeed": [TxType.PERSISTENT],
"LiveParameters": [TxType.PERSISTENT],

@ -15,6 +15,13 @@ assert monotonic_time
assert sec_since_boot
# time step for each process
DT_CTRL = 0.01 # controlsd
DT_PLAN = 0.05 # mpc
DT_MDL = 0.05 # model
DT_DMON = 0.1 # driver monitoring
ffi = FFI()
ffi.cdef("long syscall(long number, ...);")
libc = ffi.dlopen(None)

@ -1,6 +1,5 @@
import numpy as np
import common.transformations.orientation as orient
import cv2
import math
FULL_FRAME_SIZE = (1164, 874)
@ -126,6 +125,8 @@ def img_from_device(pt_device):
#TODO please use generic img transform below
def rotate_img(img, eulers, crop=None, intrinsics=eon_intrinsics):
import cv2
size = img.shape[:2]
rot = orient.rot_from_euler(eulers)
quadrangle = np.array([[0, 0],
@ -162,6 +163,8 @@ def transform_img(base_img,
output_size=None,
pretransform=None,
top_hacks=True):
import cv2
size = base_img.shape[:2]
if not output_size:
output_size = size[::-1]
@ -204,10 +207,10 @@ def transform_img(base_img,
def yuv_crop(frame, output_size, center=None):
# output_size in camera coordinates so u,v
# center in array coordinates so row, column
import cv2
rgb = cv2.cvtColor(frame, cv2.COLOR_YUV2RGB_I420)
if not center:
center = (rgb.shape[0]/2, rgb.shape[1]/2)
rgb_crop = rgb[center[0] - output_size[1]/2: center[0] + output_size[1]/2,
center[1] - output_size[0]/2: center[1] + output_size[0]/2]
return cv2.cvtColor(rgb_crop, cv2.COLOR_RGB2YUV_I420)

@ -0,0 +1,88 @@
CC = clang
CXX = clang++
PHONELIBS = ../../phonelibs
WARN_FLAGS = -Werror=implicit-function-declaration \
-Werror=incompatible-pointer-types \
-Werror=int-conversion \
-Werror=return-type \
-Werror=format-extra-args
CFLAGS = -std=gnu11 -g -fPIC -O2 $(WARN_FLAGS)
CXXFLAGS = -std=c++11 -g -fPIC -O2 $(WARN_FLAGS)
CURL_FLAGS = -I$(PHONELIBS)/curl/include
CURL_LIBS = $(PHONELIBS)/curl/lib/libcurl.a \
$(PHONELIBS)/zlib/lib/libz.a
BORINGSSL_FLAGS = -I$(PHONELIBS)/boringssl/include
BORINGSSL_LIBS = $(PHONELIBS)/boringssl/lib/libssl_static.a \
$(PHONELIBS)/boringssl/lib/libcrypto_static.a \
NANOVG_FLAGS = -I$(PHONELIBS)/nanovg
JSON11_FLAGS = -I$(PHONELIBS)/json11
OPENGL_LIBS = -lGLESv3
FRAMEBUFFER_LIBS = -lutils -lgui -lEGL
.PHONY: all
all: updater
OBJS = courbd.ttf.o \
../../selfdrive/common/touch.o \
../../selfdrive/common/framebuffer.o \
$(PHONELIBS)/json11/json11.o \
$(PHONELIBS)/nanovg/nanovg.o
DEPS := $(OBJS:.o=.d)
updater: updater.o $(OBJS)
@echo "[ LINK ] $@"
$(CXX) $(CPPFLAGS) -fPIC -o 'updater' $^ \
$(FRAMEBUFFER_LIBS) \
$(CURL_LIBS) \
$(BORINGSSL_LIBS) \
-L/system/vendor/lib64 \
$(OPENGL_LIBS) \
-lcutils -lm -llog
strip updater
courbd.ttf.o: ../../selfdrive/assets/courbd.ttf
@echo "[ bin2o ] $@"
cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)'
%.o: %.c
mkdir -p $(@D)
@echo "[ CC ] $@"
$(CC) $(CPPFLAGS) $(CFLAGS) \
-I../.. \
-I$(PHONELIBS)/android_frameworks_native/include \
-I$(PHONELIBS)/android_system_core/include \
-I$(PHONELIBS)/android_hardware_libhardware/include \
$(NANOVG_FLAGS) \
-c -o '$@' '$<'
%.o: %.cc
mkdir -p $(@D)
@echo "[ CXX ] $@"
$(CXX) $(CPPFLAGS) $(CXXFLAGS) \
-I../../selfdrive \
-I../../ \
-I$(PHONELIBS)/android_frameworks_native/include \
-I$(PHONELIBS)/android_system_core/include \
-I$(PHONELIBS)/android_hardware_libhardware/include \
$(NANOVG_FLAGS) \
$(JSON11_FLAGS) \
$(CURL_FLAGS) \
$(BORINGSSL_FLAGS) \
-c -o '$@' '$<'
.PHONY: clean
clean:
rm -f $(OBJS) $(DEPS)
-include $(DEPS)

@ -0,0 +1,7 @@
{
"ota_url": "https://commadist.azureedge.net/neosupdate/ota-signed-c992abb59cbaf6588f51055db52db619061107851773fc8480acb8bb5d77a28f.zip",
"ota_hash": "c992abb59cbaf6588f51055db52db619061107851773fc8480acb8bb5d77a28f",
"recovery_url": "https://commadist.azureedge.net/neosupdate/recovery-af099a84cfd7b91266090779238ac358278948dcde2dcfa0fbca6e8397366f0a.img",
"recovery_len": 15136044,
"recovery_hash": "af099a84cfd7b91266090779238ac358278948dcde2dcfa0fbca6e8397366f0a"
}

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:206205b51ce5bfd3c387cb961302879b72d1e1ea3e81bb8b59dbbb7109197142
size 2501608
oid sha256:743ba86c3b4d643272c11eba28e2b0a8824c542caa613a94ff6a2f01c37e54a7
size 2501656

@ -0,0 +1,675 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <string>
#include <sstream>
#include <fstream>
#include <mutex>
#include <thread>
#include <curl/curl.h>
#include <openssl/sha.h>
#include <GLES3/gl3.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "nanovg.h"
#define NANOVG_GLES3_IMPLEMENTATION
#include "nanovg_gl.h"
#include "nanovg_gl_utils.h"
#include "json11.hpp"
#include "common/framebuffer.h"
#include "common/touch.h"
#include "common/utilpp.h"
#define USER_AGENT "NEOSUpdater-0.2"
#define MANIFEST_URL_EON_STAGING "https://github.com/commaai/eon-neos/raw/master/update.staging.json"
#define MANIFEST_URL_EON_LOCAL "http://192.168.5.1:8000/neosupdate/update.local.json"
#define MANIFEST_URL_EON "https://github.com/commaai/eon-neos/raw/master/update.json"
const char *manifest_url = MANIFEST_URL_EON;
#define RECOVERY_DEV "/dev/block/bootdevice/by-name/recovery"
#define RECOVERY_COMMAND "/cache/recovery/command"
#define UPDATE_DIR "/data/neoupdate"
extern const uint8_t bin_courbd[] asm("_binary_courbd_ttf_start");
extern const uint8_t bin_courbd_end[] asm("_binary_courbd_ttf_end");
namespace {
std::string sha256_file(std::string fn, size_t limit=0) {
SHA256_CTX ctx;
SHA256_Init(&ctx);
FILE *file = fopen(fn.c_str(), "rb");
if (!file) return "";
const size_t buf_size = 8192;
std::unique_ptr<char[]> buffer( new char[ buf_size ] );
bool read_limit = (limit != 0);
while (true) {
size_t read_size = buf_size;
if (read_limit) read_size = std::min(read_size, limit);
size_t bytes_read = fread(buffer.get(), 1, read_size, file);
if (!bytes_read) break;
SHA256_Update(&ctx, buffer.get(), bytes_read);
if (read_limit) {
limit -= bytes_read;
if (limit == 0) break;
}
}
uint8_t hash[SHA256_DIGEST_LENGTH];
SHA256_Final(hash, &ctx);
fclose(file);
return util::tohex(hash, sizeof(hash));
}
size_t download_string_write(void *ptr, size_t size, size_t nmeb, void *up) {
size_t sz = size * nmeb;
((std::string*)up)->append((char*)ptr, sz);
return sz;
}
std::string download_string(CURL *curl, std::string url) {
std::string os;
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_USERAGENT, USER_AGENT);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(curl, CURLOPT_RESUME_FROM, 0);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, download_string_write);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &os);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK) {
return "";
}
return os;
}
size_t download_file_write(void *ptr, size_t size, size_t nmeb, void *up) {
return fwrite(ptr, size, nmeb, (FILE*)up);
}
bool check_battery() {
std::string bat_cap_s = util::read_file("/sys/class/power_supply/battery/capacity");
int bat_cap = atoi(bat_cap_s.c_str());
std::string current_now_s = util::read_file("/sys/class/power_supply/battery/current_now");
int current_now = atoi(current_now_s.c_str());
return bat_cap > 35 || (current_now < 0 && bat_cap > 10);
}
bool check_space() {
struct statvfs stat;
if (statvfs("/data/", &stat) != 0) {
return false;
}
size_t space = stat.f_bsize * stat.f_bavail;
return space > 2000000000ULL; // 2GB
}
static void start_settings_activity(const char* name) {
char launch_cmd[1024];
snprintf(launch_cmd, sizeof(launch_cmd),
"am start -W --ez :settings:show_fragment_as_subsetting true -n 'com.android.settings/.%s'", name);
system(launch_cmd);
}
struct Updater {
bool do_exit = false;
TouchState touch;
int fb_w, fb_h;
EGLDisplay display;
EGLSurface surface;
FramebufferState *fb = NULL;
NVGcontext *vg = NULL;
int font;
std::thread update_thread_handle;
std::mutex lock;
// i hate state machines give me coroutines already
enum UpdateState {
CONFIRMATION,
RUNNING,
ERROR,
};
UpdateState state;
std::string progress_text;
float progress_frac;
std::string error_text;
// button
int b_x, b_w, b_y, b_h;
int balt_x;
CURL *curl = NULL;
Updater() {
touch_init(&touch);
fb = framebuffer_init("updater", 0x00001000, false,
&display, &surface, &fb_w, &fb_h);
assert(fb);
vg = nvgCreateGLES3(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
assert(vg);
font = nvgCreateFontMem(vg, "courbd", (unsigned char*)bin_courbd, (bin_courbd_end - bin_courbd), 0);
assert(font >= 0);
b_w = 600;
balt_x = 200;
b_x = fb_w-b_w-200;
b_y = 700;
b_h = 250;
state = CONFIRMATION;
}
int download_file_xferinfo(curl_off_t dltotal, curl_off_t dlno,
curl_off_t ultotal, curl_off_t ulnow) {
{
std::lock_guard<std::mutex> guard(lock);
if (dltotal != 0) {
progress_frac = (float) dlno / dltotal;
}
}
// printf("info: %ld %ld %f\n", dltotal, dlno, progress_frac);
return 0;
}
bool download_file(std::string url, std::string out_fn) {
FILE *of = fopen(out_fn.c_str(), "ab");
assert(of);
CURLcode res;
long last_resume_from = 0;
fseek(of, 0, SEEK_END);
int tries = 4;
bool ret = false;
while (true) {
long resume_from = ftell(of);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt(curl, CURLOPT_USERAGENT, USER_AGENT);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(curl, CURLOPT_RESUME_FROM, resume_from);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, download_file_write);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, of);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this);
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, &Updater::download_file_xferinfo);
CURLcode res = curl_easy_perform(curl);
long response_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
// double content_length = 0.0;
// curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &content_length);
printf("download %s res %d, code %ld, resume from %ld\n", url.c_str(), res, response_code, resume_from);
if (res == CURLE_OK) {
ret = true;
break;
} else if (res == CURLE_HTTP_RETURNED_ERROR && response_code == 416) {
// failed because the file is already complete?
ret = true;
break;
} else if (resume_from == last_resume_from) {
// failed and dind't make make forward progress. only retry a couple times
tries--;
if (tries <= 0) {
break;
}
}
last_resume_from = resume_from;
}
// printf("res %d\n", res);
// printf("- %ld %f\n", response_code, content_length);
fclose(of);
return ret;
}
void set_progress(std::string text) {
std::lock_guard<std::mutex> guard(lock);
progress_text = text;
}
void set_error(std::string text) {
std::lock_guard<std::mutex> guard(lock);
error_text = text;
state = ERROR;
}
std::string stage_download(std::string url, std::string hash, std::string name) {
std::string out_fn = UPDATE_DIR "/" + util::base_name(url);
set_progress("downloading " + name + "...");
bool r = download_file(url, out_fn);
if (!r) {
set_error("failed to download " + name);
return "";
}
set_progress("verifying " + name + "...");
std::string fn_hash = sha256_file(out_fn);
printf("got %s hash: %s\n", name.c_str(), hash.c_str());
if (fn_hash != hash) {
set_error(name + " was corrupt");
unlink(out_fn.c_str());
return "";
}
return out_fn;
}
void run_stages() {
curl = curl_easy_init();
assert(curl);
if (!check_battery()) {
set_error("Please plug power in to your EON and wait for charge");
return;
}
if (!check_space()) {
set_error("2GB of free space required to update");
return;
}
mkdir(UPDATE_DIR, 0777);
const int EON = (access("/EON", F_OK) != -1);
set_progress("finding latest version...");
std::string manifest_s;
if (EON) {
manifest_s = download_string(curl, manifest_url);
} else {
// don't update NEO
exit(0);
}
printf("manifest: %s\n", manifest_s.c_str());
std::string err;
auto manifest = json11::Json::parse(manifest_s, err);
if (manifest.is_null() || !err.empty()) {
set_error("failed to load update manifest");
return;
}
std::string ota_url = manifest["ota_url"].string_value();
std::string ota_hash = manifest["ota_hash"].string_value();
std::string recovery_url = manifest["recovery_url"].string_value();
std::string recovery_hash = manifest["recovery_hash"].string_value();
int recovery_len = manifest["recovery_len"].int_value();
// std::string installer_url = manifest["installer_url"].string_value();
// std::string installer_hash = manifest["installer_hash"].string_value();
if (ota_url.empty() || ota_hash.empty()) {
set_error("invalid update manifest");
return;
}
// std::string installer_fn = stage_download(installer_url, installer_hash, "installer");
// if (installer_fn.empty()) {
// //error'd
// return;
// }
std::string recovery_fn;
if (recovery_url.empty() || recovery_hash.empty() || recovery_len == 0) {
set_progress("skipping recovery flash...");
} else {
// only download the recovery if it differs from what's flashed
set_progress("checking recovery...");
std::string existing_recovery_hash = sha256_file(RECOVERY_DEV, recovery_len);
printf("existing recovery hash: %s\n", existing_recovery_hash.c_str());
if (existing_recovery_hash != recovery_hash) {
recovery_fn = stage_download(recovery_url, recovery_hash, "recovery");
if (recovery_fn.empty()) {
// error'd
return;
}
}
}
std::string ota_fn = stage_download(ota_url, ota_hash, "update");
if (ota_fn.empty()) {
//error'd
return;
}
if (!check_battery()) {
set_error("must have at least 35% battery to update");
return;
}
if (!recovery_fn.empty()) {
// flash recovery
set_progress("flashing recovery...");
FILE *flash_file = fopen(recovery_fn.c_str(), "rb");
if (!flash_file) {
set_error("failed to flash recovery");
return;
}
FILE *recovery_dev = fopen(RECOVERY_DEV, "w+b");
if (!recovery_dev) {
fclose(flash_file);
set_error("failed to flash recovery");
return;
}
const size_t buf_size = 4096;
std::unique_ptr<char[]> buffer( new char[ buf_size ] );
while (true) {
size_t bytes_read = fread(buffer.get(), 1, buf_size, flash_file);
if (!bytes_read) break;
size_t bytes_written = fwrite(buffer.get(), 1, bytes_read, recovery_dev);
if (bytes_read != bytes_written) {
fclose(recovery_dev);
fclose(flash_file);
set_error("failed to flash recovery: write failed");
return;
}
}
fclose(recovery_dev);
fclose(flash_file);
set_progress("verifying flash...");
std::string new_recovery_hash = sha256_file(RECOVERY_DEV, recovery_len);
printf("new recovery hash: %s\n", new_recovery_hash.c_str());
if (new_recovery_hash != recovery_hash) {
set_error("recovery flash corrupted");
return;
}
}
// write arguments to recovery
FILE *cmd_file = fopen(RECOVERY_COMMAND, "wb");
if (!cmd_file) {
set_error("failed to reboot into recovery");
return;
}
fprintf(cmd_file, "--update_package=%s\n", ota_fn.c_str());
fclose(cmd_file);
set_progress("rebooting");
// remove the continue.sh so we come back into the setup.
// maybe we should go directly into the installer, but what if we don't come back with internet? :/
//unlink("/data/data/com.termux/files/continue.sh");
// TODO: this should be generic between android versions
// IPowerManager.reboot(confirm=false, reason="recovery", wait=true)
system("service call power 16 i32 0 s16 recovery i32 1");
while(1) pause();
// execl("/system/bin/reboot", "recovery");
// set_error("failed to reboot into recovery");
}
void draw_ack_screen(const char *message, const char *button, const char *altbutton) {
nvgFontSize(vg, 96.0f);
nvgFillColor(vg, nvgRGBA(255,255,255,255));
nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_BASELINE);
nvgTextBox(vg, 50, 100, fb_w-100, message, NULL);
// draw button
if (button) {
nvgBeginPath(vg);
nvgFillColor(vg, nvgRGBA(0, 0, 0, 255));
nvgRoundedRect(vg, b_x, b_y, b_w, b_h, 20);
nvgFill(vg);
nvgFillColor(vg, nvgRGBA(255, 255, 255, 255));
nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
nvgText(vg, b_x+b_w/2, b_y+b_h/2, button, NULL);
nvgBeginPath(vg);
nvgStrokeColor(vg, nvgRGBA(255, 255, 255, 255));
nvgStrokeWidth(vg, 5);
nvgRoundedRect(vg, b_x, b_y, b_w, b_h, 20);
nvgStroke(vg);
}
// draw button
if (altbutton) {
nvgBeginPath(vg);
nvgFillColor(vg, nvgRGBA(0, 0, 0, 255));
nvgRoundedRect(vg, balt_x, b_y, b_w, b_h, 20);
nvgFill(vg);
nvgFillColor(vg, nvgRGBA(255, 255, 255, 255));
nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
nvgText(vg, balt_x+b_w/2, b_y+b_h/2, altbutton, NULL);
nvgBeginPath(vg);
nvgStrokeColor(vg, nvgRGBA(255, 255, 255, 255));
nvgStrokeWidth(vg, 5);
nvgRoundedRect(vg, balt_x, b_y, b_w, b_h, 20);
nvgStroke(vg);
}
}
void draw_progress_screen() {
// draw progress message
nvgFontSize(vg, 64.0f);
nvgFillColor(vg, nvgRGBA(255,255,255,255));
nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE);
nvgTextBox(vg, 0, 700, fb_w, progress_text.c_str(), NULL);
// draw progress bar
{
int progress_width = 800;
int progress_x = fb_w/2-progress_width/2;
int progress_y = 768;
int progress_height = 15;
int powerprompt_y = 512;
nvgText(vg, fb_w/2, powerprompt_y, "Ensure EON is connected to power", NULL);
NVGpaint paint = nvgBoxGradient(
vg, progress_x + 1, progress_y + 1,
progress_width - 2, progress_height, 3, 4, nvgRGB(0, 32, 0), nvgRGB(0, 92, 0));
nvgBeginPath(vg);
nvgRoundedRect(vg, progress_x, progress_y, progress_width, progress_height, 3);
nvgFillPaint(vg, paint);
nvgFill(vg);
float value = std::min(std::max(0.0f, progress_frac), 1.0f);
int bar_pos = ((progress_width - 2) * value);
paint = nvgBoxGradient(
vg, progress_x, progress_y,
bar_pos+1.5f, progress_height-1, 3, 4,
nvgRGB(220, 100, 0), nvgRGB(128, 100, 0));
nvgBeginPath(vg);
nvgRoundedRect(
vg, progress_x+1, progress_y+1,
bar_pos, progress_height-2, 3);
nvgFillPaint(vg, paint);
nvgFill(vg);
}
}
void ui_draw() {
std::lock_guard<std::mutex> guard(lock);
nvgBeginFrame(vg, fb_w, fb_h, 1.0f);
switch (state) {
case CONFIRMATION:
draw_ack_screen("An upgrade to NEOS is required.\n\n"
"Your device will now be reset and upgraded. You may want to connect to wifi as download is around 1 GB\nData on device shouldn't be lost.",
"continue",
"wifi");
break;
case RUNNING:
draw_progress_screen();
break;
case ERROR:
draw_ack_screen(("ERROR: " + error_text + "\n\nYou will need to retry").c_str(), NULL, "exit");
break;
}
nvgEndFrame(vg);
}
void ui_update() {
std::lock_guard<std::mutex> guard(lock);
switch (state) {
case ERROR:
case CONFIRMATION: {
int touch_x = -1, touch_y = -1;
int res = touch_poll(&touch, &touch_x, &touch_y, 0);
if (res == 1 && !is_settings_active()) {
if (touch_x >= b_x && touch_x < b_x+b_w && touch_y >= b_y && touch_y < b_y+b_h) {
if (state == CONFIRMATION) {
state = RUNNING;
update_thread_handle = std::thread(&Updater::run_stages, this);
}
}
if (touch_x >= balt_x && touch_x < balt_x+b_w && touch_y >= b_y && touch_y < b_y+b_h) {
if (state == CONFIRMATION) {
start_settings_activity("Settings$WifiSettingsActivity");
} else if (state == ERROR) {
do_exit = 1;
}
}
}
}
default:
break;
}
}
void go() {
while (!do_exit) {
ui_update();
glClearColor(0.19, 0.09, 0.2, 1.0);
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
ui_draw();
glDisable(GL_BLEND);
eglSwapBuffers(display, surface);
assert(glGetError() == GL_NO_ERROR);
// no simple way to do 30fps vsync with surfaceflinger...
usleep(30000);
}
if (update_thread_handle.joinable()) {
update_thread_handle.join();
}
system("service call power 16 i32 0 i32 0 i32 1");
}
bool is_settings_active() {
FILE *fp;
char sys_output[4096];
fp = popen("/bin/dumpsys window windows", "r");
if (fp == NULL) {
return false;
}
bool active = false;
while (fgets(sys_output, sizeof(sys_output), fp) != NULL) {
if (strstr(sys_output, "mCurrentFocus=null") != NULL) {
break;
}
if (strstr(sys_output, "mCurrentFocus=Window") != NULL) {
active = true;
break;
}
}
pclose(fp);
return active;
}
};
}
int main(int argc, char *argv[]) {
if (argc > 1) {
if (strcmp(argv[1], "local") == 0) {
manifest_url = MANIFEST_URL_EON_LOCAL;
} else if (strcmp(argv[1], "staging") == 0) {
manifest_url = MANIFEST_URL_EON_STAGING;
} else {
manifest_url = argv[1];
}
}
printf("updating from %s\n", manifest_url);
Updater updater;
updater.go();
return 0;
}

@ -1,5 +1,11 @@
#!/usr/bin/bash
export OMP_NUM_THREADS=1
export MKL_NUM_THREADS=1
export NUMEXPR_NUM_THREADS=1
export OPENBLAS_NUM_THREADS=1
export VECLIB_MAXIMUM_THREADS=1
if [ -z "$PASSIVE" ]; then
export PASSIVE="1"
fi

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d1805ad557a93999b787ab1fd66f4bcef7d25226b123bd4f49774340f2e7476c
size 6354536
oid sha256:46b4433f49e6d54ced1049e03aed650f6cb6de6d243ae64167945150935d7cd8
size 12039472

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e9f15383e6c4c5b38d23ebddc61e1ea470e3bfe1162bc5541731110c44c5e930
size 218

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4f5dfc20e99151c75d84292c20078403e74a57845b67b7a7a6a4b914bc7489d7
size 6310

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1cc3d193d044c640dc508a71edade54dfbc8eda63ecd8357a56140040b9c7edb
size 1297

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:115e60c96995ddb54fb0e512f6daf22d4202f837b184516387db5d23d26a5646
size 3321

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6224c4f8ab7b39d8adeb75546a6525079ffedfeea5237cbd36e867f3cee04803
size 24230

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:522965edc66e550247798a34aea163332039153f24634d89258d291dc273e3c0
size 50206

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:670bbc519eb78fc02e3d219bb22852094a822c93059cb0d8b84bfb589bef69d2
size 28013

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ac6faedcf48e9e7b4d5d3d954902e89ba4cb10547bf3b95e6d0b18d449622380
size 9362

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fc9d7e479c930899802a616233eb19cf35c348f1983e58e0b19009314f70e300
size 3827

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:04f85d119fc222abd65aef1f57f8e03a94134c272b95ed781e8f3791c64d973a
size 11780

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ee90636296c75189310323ce3bf1b4a2f893b04c46c0e4f6f103b9a013a60033
size 4316

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:170b6129e63451b96442573ecc95758388176d8793d5a979b00bf5346856716e
size 1312

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fd3e7a17778fa696a0fce301b5d50ed840d555b804f6d1b5b8f03d7fbb39283b
size 1645

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7cc1c4048bdea60287aa1d882bc7d6f6022650f9046e25aff467460e824682eb
size 1360

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1adbf47e36c389ce0b35d7e71d5dc554b395c773354f492fb05014f596a62fbb
size 13375

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2a5447e1652b16d9980d3b2c49f0c768ae72f3fbca63e53327db1f6792c017c9
size 4478

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:101ddabd30d19118826fed11932cc31f93ca66f431577f9da332276ebe2b836c
size 1863

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2f1458af50d003e0ecdce63c3898ff3d4ea8dd377d8c578bf3585224f09e0a19
size 9558

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c2a41eb4ce0779c2b1a8688963d941e42d865bb329f00b9b0afd1a47ce13f457
size 3487

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d4f7436534cc53b22144089c1b4f1a2e2f0e46a73f7e34baac65f99f0c65b36e
size 1443

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3ef80851c4f0dabc111ca30f20fab1ad6986f3f0d0e647c0ff215cf0875b95d3
size 1847

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:78aff1f5e3fcdd820a67090f0db2dc8354c3cce3bace7da137739e7c0698b3d0
size 4135

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:84a970cfdf33f86843304d0f49b9bde40cfd36b538c6e92cf8fccbb8101eba39
size 3670

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:757ac756acdb326d3b40dc1e01e56c38b4466cb188b0e2db34ea54407e28f14b
size 1909

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ca3771c1f65b2e9e95be641185f3948d06b41e274cfd84faa2237d926000a7d8
size 4198

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:21d16d34c5fd57030ad898f7b4c658f56a0cb16ddc187acbb514abaed91d3524
size 1946

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ec7353283565bfabfec563ffe770d538816c7f014f71268467f25535f83ce4b9
size 1461

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:dfd9355ceea4af60c603125897f8f1286488c415685a94849282eaf55f88a4cf
size 1587

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cccdfcc2f97ae9f4555108f88d0afccb05ce60dc77ca5ce77ef9bed336439079
size 2967

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:673dcc1b4783a037c0bd740dd6eb197abfedb4b60652b9f197eb42d2bbbb111d
size 2652

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c3588b911e0996b8c3d1302159543078a7f47f284a643757baaa064b33ef54f7
size 5719

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f1df1400d1802efa1493b12011c42a0463a78992fdcede39465a5a5c607d5f12
size 5346

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:03399faeadd032a6ee04243da9598731155120ce5e0ba561176eeb5a23448a64
size 2760

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2bb01005609d90b2764e74a286439d8ce18384ed49c5da5a32514a98199d3268
size 5794

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6b7097beb61dd5f61c97ed00811ce3fdc8f54eb924966cb8df1c90587157ed29
size 1989

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f6b79dd4de99b1641eed90ecdfc1bebe22b8eced1952f76d0817715ddeca1be2
size 1761

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b8ebc04536bf5b9a3b8476fc69b16af88b4f7e270cc25dd5593775d8fd168e4a
size 3058

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:91e920eb91a889b7ebe4f75cf93d85974f15f56830bd74446274c297e45ebb1b
size 1478

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f2fa384a16c2dab3f5da239a403d475d1f66929c49546a68fef185f514b88f84
size 1779

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:20ff33d9c67fc9f1dda1185a0c22233ba76fe802d9cd0baa1dc4d605866c2de5
size 2969

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:67a6a070382d161ad4986058dcee5796d6872c1fbbc1e4ebf9405a2bb149a00b
size 2121

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a56179f0413127e1f482b52ed33484cd5614d0e4c3f5b73339e63855e5f33a5c
size 16085

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0d2b02316d73c9c8162200def733398df09c65d0cd095f36b41cb85b65e99aa0
size 2537

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:855e3f340536dc4f8adcc36d9008462581b03b1896424ab1e280d06d48eef8b2
size 2089

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cb9b5d3a8de374d4d321483dbad9f87d82aed3e5bae94b4ea95f0469f921b5aa
size 4161

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:265061758f26c7f49c73d3bd5b378a19dd6a85c2670184c425329db726f40f62
size 5538

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f64238396d565007970e2dae18e6512f78c76ef7f25afb7bfecca2781410cff1
size 850

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1dd4dd8ea31194aec5eb308448a84f68e00686c2e388ffdaa0b3d59ecbeb7605
size 2925

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6da33fd21ca28b94f486cc7c3d8f0963aefd5e281681dad2c59e27b0649dfda7
size 4146

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a7a2bce5e0fd0dbabf73d310d5b3396befca8a40fb3860c36fe99f5cbcebe552
size 3771

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e188a71436fdb40a19171bee104f0faf35fc73d7b170420ec468c1053ffafe2b
size 3770

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bae5d175a8754ab82f351203496381c9f988ffa9f1549dfd47254280cbc572c1
size 8057

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bbcdb1e69a5d74aa1c549fa191853a03536d9408fef9023a98ed5436b498c912
size 11790

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2fd6327d02df20b3560bcbbfc0f1c9cab5bd506b2bc26a78f2bd3abcebdcf9e8
size 1144

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:78dd17ec37b92b113c1e30c226458ebec4006c75ec71d3324e659f0b6334c756
size 10433

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:245631b236d2ca272f3d565eefe70af92be7a2cbd7ef73b2cf6d276b9bad1090
size 5494

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:339188da63c72c067a7b88bce21452d20d42f62bf9e0a9f23013b64e51121ad9
size 11552

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:78197bb11633009e50538af6822158be2d00231c3e25f340f8914756833ae006
size 4683

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0b17767bfe0b7796f422fb9132a23e7bddf1ed29111562ecb49cdf0f42d52b8a
size 3979

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:65f7cd6b57b6afa4afb020769c45ce7c34ecb28aa24e2a32db422ec049501ae7
size 22456

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a5f5ad65254a75518430630e0efb42437717c1b5d5c779d8979a95d4bcfd43b2
size 1404

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7e2756965873ef04d7a5e9c74d129f987c7bda68cc6c2bcf1621ec7f607d8655
size 892

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f27a7d810fab79a182925bcbad91845e8b0fcd23e34450187de2120b1b651b20
size 4207

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0c041de77a8d30abba6fdc0cfd6a1d3e12e0542d2d36db0ad50fbffde103a9a9
size 2260

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:190e6fd0d3aa51febe4425f207c9ccb3f3d477df30de4ecd47cf15d72b07cc2a
size 1797

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7cc59712c78a22786ea7ea8151b49fa0882f4db09f79e5551f87780933378cbd
size 12943

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:64566e05d8794a536fb6a7a86bd5125c76b54f5ce4c1c95fa1cfe810f3a4f4f8
size 24769

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d1df0d4b3379b6daebd902add7e38a8f53b90c3b7c25b1d8855fd44a043fe650
size 4488
oid sha256:f34c4a8a04b6b04c012bf730d7e17ec379af9c1a1b06f3bf5d093ed3a182b18d
size 2071

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5eae57aaf0445cb13dd971a5e050835d3dfe0d8a73818d9d700850845012f3f0
size 1947

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b6f1016bc60c8b046c4010d09b674d5b65812bc58abe1345de2e5bbbae8ccb3a
size 1873

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4bf890c484480988656a5ad46d265d1d6c82832a521a2168a199f6ff5a77bfb7
size 6461

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d64ef9a3ce9b4cf20a1c68ccf2fda5d8afeaa00c87b51fbfe424cea50ed4f3ce
size 2916

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fef9e2cf234338f057d1ca7fd572c288dbb55039c64e5430bbc4519818806d6d
size 3579

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1e7abdb7046401e50d7a00bdf3e0af74c8cb6e29eec684559beb203f2dc2cb55
size 3079

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4e6e156d6f99b5b5fe1ea69241d466eafda734c20d76b506b976028695486d09
size 2528

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e126e8f6dc76e9f5ac8ceeb24f1c1add7d77b5d53e9b7281d37593d8e7bae956
size 7596

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e3762e8cb68493ea8951bfe72510de46735e750e0acacb5e1abff719508c4634
size 13515

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c32afc8cbfaa4cb365712a7a5dfe32ab25c9f7c9fb9aa604ba0008375ac6af42
size 9287

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5e8d9b67e029a12641f472d341eb2f7e59ced566e7a0ed163158679eb09dfcb3
size 3360

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7675d7d60165054bb459a20959e179a66cb4338db61d5da468c022be23e992ef
size 1356

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save