* purge begins

* release files

* remove those

* no more android

* only qt

* text and spinner

* neos update script

* update sounds

* update cpu usage

* all done

Co-authored-by: Comma Device <device@comma.ai>
albatross
Adeeb Shihadeh 2021-03-24 14:30:41 -07:00 committed by GitHub
parent 49748d5dc1
commit e76c80ffa1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 74 additions and 1052 deletions

1
.gitattributes vendored
View File

@ -3,7 +3,6 @@
*.onnx filter=lfs diff=lfs merge=lfs -text
*.pb filter=lfs diff=lfs merge=lfs -text
*.bin filter=lfs diff=lfs merge=lfs -text
*.apk filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.ipynb filter=nbstripout -diff
external/ffmpeg/bin/ffmpeg_cuda filter=lfs diff=lfs merge=lfs -text

2
.gitignore vendored
View File

@ -59,8 +59,6 @@ notebooks
xx
hyperthneed
panda_jungle
apks
openpilot-apks
.coverage*
coverage.xml

2
Jenkinsfile vendored
View File

@ -130,8 +130,6 @@ pipeline {
["onroad tests", "cd selfdrive/test/ && ./test_onroad.py"],
["build devel", "cd release && CI_PUSH=${env.CI_PUSH} ./build_devel.sh"],
["test car interfaces", "cd selfdrive/car/tests/ && ./test_car_interfaces.py"],
["test spinner build", "cd selfdrive/ui/spinner && make clean && make"],
["test text window build", "cd selfdrive/ui/text && make clean && make"],
])
}
}

View File

@ -312,7 +312,6 @@ And [follow us on Twitter](https://twitter.com/comma_ai).
Directory Structure
------
.
├── apk # The apk files used for the UI
├── cereal # The messaging spec and libs used for all logs
├── common # Library like functionality we've developed here
├── installer/updater # Manages auto-updates of openpilot

BIN
apk/ai.comma.plus.offroad.apk (Stored with Git LFS)

Binary file not shown.

View File

@ -6,8 +6,6 @@ export NUMEXPR_NUM_THREADS=1
export OPENBLAS_NUM_THREADS=1
export VECLIB_MAXIMUM_THREADS=1
export QT=1
if [ -z "$REQUIRED_NEOS_VERSION" ]; then
export REQUIRED_NEOS_VERSION="16.1"
fi

View File

@ -13,8 +13,6 @@ RELEASES.md
SAFETY.md
site_scons/site_tools/cython.py
apk/ai.comma*.apk
common/.gitignore
common/__init__.py
common/gpio.py
@ -267,7 +265,6 @@ selfdrive/hardware/base.h
selfdrive/hardware/base.py
selfdrive/hardware/hw.h
selfdrive/hardware/eon/__init__.py
selfdrive/hardware/eon/apk.py
selfdrive/hardware/eon/hardware.h
selfdrive/hardware/eon/hardware.py
selfdrive/hardware/tici/__init__.py
@ -344,13 +341,6 @@ selfdrive/ui/*.hpp
selfdrive/ui/ui
selfdrive/ui/text
selfdrive/ui/spinner
selfdrive/ui/android/spinner/Makefile
selfdrive/ui/android/spinner/spinner
selfdrive/ui/android/spinner/spinner.c
selfdrive/ui/android/text/Makefile
selfdrive/ui/android/text/text
selfdrive/ui/android/text/text.cc
selfdrive/ui/qt/*.cc
selfdrive/ui/qt/*.hpp
@ -359,9 +349,6 @@ selfdrive/ui/qt/offroad/*.hpp
selfdrive/ui/qt/widgets/*.cc
selfdrive/ui/qt/widgets/*.hpp
selfdrive/ui/android/*.cc
selfdrive/ui/android/*.hpp
selfdrive/camerad/SConscript
selfdrive/camerad/main.cc

View File

@ -1,105 +0,0 @@
import os
import subprocess
import glob
import hashlib
import shutil
from common.basedir import BASEDIR
from selfdrive.swaglog import cloudlog
android_packages = ("ai.comma.plus.offroad",)
def get_installed_apks():
dat = subprocess.check_output(["pm", "list", "packages", "-f"], encoding='utf8').strip().split("\n")
ret = {}
for x in dat:
if x.startswith("package:"):
v, k = x.split("package:")[1].split("=")
ret[k] = v
return ret
def install_apk(path):
# can only install from world readable path
install_path = "/sdcard/%s" % os.path.basename(path)
shutil.copyfile(path, install_path)
ret = subprocess.call(["pm", "install", "-r", install_path])
os.remove(install_path)
return ret == 0
def start_offroad():
set_package_permissions()
system("am start -n ai.comma.plus.offroad/.MainActivity")
def set_package_permissions():
try:
output = subprocess.check_output(['dumpsys', 'package', 'ai.comma.plus.offroad'], encoding="utf-8")
given_permissions = output.split("runtime permissions")[1]
except Exception:
given_permissions = ""
wanted_permissions = ["ACCESS_FINE_LOCATION", "READ_PHONE_STATE", "READ_EXTERNAL_STORAGE"]
for permission in wanted_permissions:
if permission not in given_permissions:
pm_grant("ai.comma.plus.offroad", "android.permission."+permission)
appops_set("ai.comma.plus.offroad", "SU", "allow")
appops_set("ai.comma.plus.offroad", "WIFI_SCAN", "allow")
def appops_set(package, op, mode):
system(f"LD_LIBRARY_PATH= appops set {package} {op} {mode}")
def pm_grant(package, permission):
system(f"pm grant {package} {permission}")
def system(cmd):
try:
cloudlog.info("running %s" % cmd)
subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError as e:
cloudlog.event("running failed",
cmd=e.cmd,
output=e.output[-1024:],
returncode=e.returncode)
# *** external functions ***
def update_apks():
# install apks
installed = get_installed_apks()
install_apks = glob.glob(os.path.join(BASEDIR, "apk/*.apk"))
for apk in install_apks:
app = os.path.basename(apk)[:-4]
if app not in installed:
installed[app] = None
cloudlog.info("installed apks %s" % (str(installed), ))
for app in installed.keys():
apk_path = os.path.join(BASEDIR, "apk/"+app+".apk")
if not os.path.exists(apk_path):
continue
h1 = hashlib.sha1(open(apk_path, 'rb').read()).hexdigest()
h2 = None
if installed[app] is not None:
h2 = hashlib.sha1(open(installed[app], 'rb').read()).hexdigest()
cloudlog.info("comparing version of %s %s vs %s" % (app, h1, h2))
if h2 is None or h1 != h2:
cloudlog.info("installing %s" % app)
success = install_apk(apk_path)
if not success:
cloudlog.info("needing to uninstall %s" % app)
system("pm uninstall %s" % app)
success = install_apk(apk_path)
assert success
def pm_apply_packages(cmd):
for p in android_packages:
system("pm %s %s" % (cmd, p))
if __name__ == "__main__":
update_apks()

View File

@ -0,0 +1,4 @@
#!/usr/bin/bash
ROOT=$PWD/../../..
$ROOT/installer/updater/updater "file://$ROOT/installer/updater/update.json"

View File

@ -12,9 +12,7 @@ from common.basedir import BASEDIR
from common.params import Params
from common.spinner import Spinner
from common.text_window import TextWindow
from selfdrive.hardware import EON, HARDWARE
from selfdrive.hardware.eon.apk import (pm_apply_packages, start_offroad,
update_apks)
from selfdrive.hardware import HARDWARE
from selfdrive.manager.build import MAX_BUILD_PROGRESS, PREBUILT
from selfdrive.manager.helpers import unblock_stdout
from selfdrive.manager.process import ensure_running
@ -60,9 +58,6 @@ def manager_init(spinner=None):
if params.get("Passive") is None:
raise Exception("Passive must be set to continue")
if EON:
update_apks()
os.umask(0) # Make sure we can create files with 777 permissions
# Create folders needed for msgq
@ -89,13 +84,6 @@ def manager_init(spinner=None):
crash.bind_user(id=dongle_id)
crash.bind_extra(version=version, dirty=dirty, device=HARDWARE.get_device_type())
# ensure shared libraries are readable by apks
if EON:
os.chmod(BASEDIR, 0o755)
os.chmod("/dev/shm", 0o777)
os.chmod(os.path.join(BASEDIR, "cereal"), 0o755)
os.chmod(os.path.join(BASEDIR, "cereal", "libmessaging_shared.so"), 0o755)
def manager_prepare(spinner=None):
# build all processes
@ -110,9 +98,6 @@ def manager_prepare(spinner=None):
def manager_cleanup():
if EON:
pm_apply_packages('disable')
for p in managed_processes.values():
p.stop()
@ -132,11 +117,6 @@ def manager_thread(spinner=None):
if os.getenv("BLOCK") is not None:
ignore += os.getenv("BLOCK").split(",")
# start offroad
if EON and "QT" not in os.environ:
pm_apply_packages('enable')
start_offroad()
ensure_running(managed_processes.values(), started=False, not_run=ignore)
if spinner: # close spinner when ui has started
spinner.close()

View File

@ -1,9 +1,7 @@
import time
import subprocess
from functools import wraps
from nose.tools import nottest
from selfdrive.hardware.eon.apk import update_apks, start_offroad, pm_apply_packages, android_packages
from selfdrive.hardware import PC
from selfdrive.version import training_version, terms_version
from selfdrive.manager.process_config import managed_processes
@ -49,26 +47,3 @@ def with_processes(processes, init_time=0):
return wrap
return wrapper
def with_apks():
def wrapper(func):
@wraps(func)
def wrap():
update_apks()
pm_apply_packages('enable')
start_offroad()
func()
try:
for package in android_packages:
apk_is_running = (subprocess.call(["pidof", package]) == 0)
assert apk_is_running, package
finally:
pm_apply_packages('disable')
for package in android_packages:
apk_is_not_running = (subprocess.call(["pidof", package]) == 1)
assert apk_is_not_running, package
return wrap
return wrapper

View File

@ -18,10 +18,10 @@ PROCS = [
("./loggerd", 45.0),
("selfdrive.locationd.locationd", 35.0),
("selfdrive.controls.plannerd", 20.0),
("./_ui", 15.0),
("selfdrive.locationd.paramsd", 12.0),
("./camerad", 7.07),
("./_sensord", 6.17),
("./_ui", 5.82),
("selfdrive.controls.radard", 5.67),
("./_modeld", 4.48),
("./boardd", 3.63),

View File

@ -4,7 +4,7 @@ import subprocess
from cereal import log, car
import cereal.messaging as messaging
from selfdrive.test.helpers import phone_only, with_processes
from selfdrive.test.helpers import phone_only, with_processes, set_params_enabled
from common.realtime import DT_CTRL
from selfdrive.hardware import HARDWARE
@ -13,14 +13,14 @@ AudibleAlert = car.CarControl.HUDControl.AudibleAlert
SOUNDS = {
# sound: total writes
AudibleAlert.none: 0,
AudibleAlert.chimeEngage: 85,
AudibleAlert.chimeDisengage: 85,
AudibleAlert.chimeError: 85,
AudibleAlert.chimePrompt: 85,
AudibleAlert.chimeWarning1: 80,
AudibleAlert.chimeWarning2: 107,
AudibleAlert.chimeWarning2Repeat: 177,
AudibleAlert.chimeWarningRepeat: 240,
AudibleAlert.chimeEngage: 173,
AudibleAlert.chimeDisengage: 173,
AudibleAlert.chimeError: 173,
AudibleAlert.chimePrompt: 173,
AudibleAlert.chimeWarning1: 163,
AudibleAlert.chimeWarning2: 216,
AudibleAlert.chimeWarning2Repeat: 346,
AudibleAlert.chimeWarningRepeat: 468,
}
def get_total_writes():
@ -36,7 +36,7 @@ def test_sound_card_init():
@phone_only
@with_processes(['ui', 'camerad'])
def test_alert_sounds():
set_params_enabled()
pm = messaging.PubMaster(['deviceState', 'controlsState'])
# make sure they're all defined
@ -70,3 +70,4 @@ def test_alert_sounds():
tolerance = (expected_writes % 100) * 2
actual_writes = get_total_writes() - start_writes
assert abs(expected_writes - actual_writes) <= tolerance, f"{alert_sounds[sound]}: expected {expected_writes} writes, got {actual_writes}"
#print(f"{alert_sounds[sound]}: expected {expected_writes} writes, got {actual_writes}")

View File

@ -10,59 +10,50 @@ if arch == 'aarch64':
libs += ['log', 'utils', 'gui', 'ui', 'CB', 'gsl', 'adreno_utils',
'cutils', 'uuid']
if arch == 'aarch64' and "QT" not in os.environ:
libs += ['EGL', 'GLESv3', 'gnustl_shared', 'hardware', 'OpenSLES', 'cutils', 'uuid']
linkflags = ['-Wl,-rpath=/system/lib64,-rpath=/system/comma/usr/lib']
qt_base_libs = qt_env["LIBS"] + libs + ["pthread"]
if arch == "Darwin":
del qt_base_libs[qt_base_libs.index('OpenCL')]
qt_env['FRAMEWORKS'] += ['OpenCL']
src += ["android/ui.cc", "android/sl_sound.cc"]
env.Program('_ui', src,
LINKFLAGS=linkflags,
LIBS=libs)
else:
qt_base_libs = qt_env["LIBS"] + libs + ["pthread"]
if arch == "Darwin":
del qt_base_libs[qt_base_libs.index('OpenCL')]
qt_env['FRAMEWORKS'] += ['OpenCL']
widgets_src = ["qt/widgets/input.cc", "qt/widgets/drive_stats.cc",
"qt/widgets/ssh_keys.cc", "qt/widgets/toggle.cc", "qt/widgets/controls.cc", "qt/qt_sound.cc",
"qt/widgets/offroad_alerts.cc", "qt/widgets/setup.cc", "qt/widgets/keyboard.cc",
"#phonelibs/qrcode/QrCode.cc"]
if arch != 'aarch64':
widgets_src += ["qt/offroad/networking.cc", "qt/offroad/wifiManager.cc"]
widgets_src = ["qt/widgets/input.cc", "qt/widgets/drive_stats.cc",
"qt/widgets/ssh_keys.cc", "qt/widgets/toggle.cc", "qt/widgets/controls.cc", "qt/qt_sound.cc",
"qt/widgets/offroad_alerts.cc", "qt/widgets/setup.cc", "qt/widgets/keyboard.cc",
"#phonelibs/qrcode/QrCode.cc"]
widgets = qt_env.Library("qt_widgets", widgets_src, LIBS=qt_base_libs)
qt_libs = qt_base_libs + [widgets]
if arch != 'aarch64':
widgets_src += ["qt/offroad/networking.cc", "qt/offroad/wifiManager.cc"]
# spinner and text window
qt_env.Program("qt/text", ["qt/text.cc"], LIBS=qt_base_libs)
qt_env.Program("qt/spinner", ["qt/spinner.cc"], LIBS=qt_base_libs)
widgets = qt_env.Library("qt_widgets", widgets_src, LIBS=qt_base_libs)
qt_libs = qt_base_libs + [widgets]
# build main UI
qt_src = ["qt/ui.cc", "qt/window.cc", "qt/home.cc", "qt/api.cc", "qt/offroad/settings.cc",
"qt/offroad/onboarding.cc"] + src
qt_env.Program("_ui", qt_src, LIBS=qt_libs)
qt_src = ["qt/ui.cc", "qt/window.cc", "qt/home.cc", "qt/api.cc", "qt/offroad/settings.cc",
"qt/offroad/onboarding.cc"] + src
qt_env.Program("_ui", qt_src, LIBS=qt_libs)
# setup, factory resetter, and installer
if arch != 'aarch64' and "BUILD_SETUP" in os.environ:
qt_env.Program("qt/setup/reset", ["qt/setup/reset.cc"], LIBS=qt_libs)
qt_env.Program("qt/setup/setup", ["qt/setup/setup.cc"], LIBS=qt_libs + ['curl', 'common', 'json11'])
qt_env.Program("qt/setup/wifi", ["qt/setup/wifi.cc"], LIBS=qt_libs + ['common', 'json11'])
# spinner and text window
qt_env.Program("qt/text", ["qt/text.cc"], LIBS=qt_base_libs)
qt_env.Program("qt/spinner", ["qt/spinner.cc"], LIBS=qt_base_libs)
installers = [
("openpilot", "master"),
#("openpilot_test", "release3-staging"),
#("openpilot_internal", "master"),
#("dashcam", "dashcam3-staging"),
#("dashcam_test", "dashcam3-staging"),
]
for name, branch in installers:
d = {'BRANCH': f"'\"{branch}\"'"}
if "internal" in name:
d['INTERNAL'] = "1"
# build setup, factory resetter, and installer
if "BUILD_SETUP" in os.environ:
qt_env.Program("qt/setup/reset", ["qt/setup/reset.cc"], LIBS=qt_libs)
qt_env.Program("qt/setup/setup", ["qt/setup/setup.cc"], LIBS=qt_libs + ['curl', 'common', 'json11'])
qt_env.Program("qt/setup/wifi", ["qt/setup/wifi.cc"], LIBS=qt_libs + ['common', 'json11'])
installers = [
("openpilot", "master"),
#("openpilot_test", "release3-staging"),
#("openpilot_internal", "master"),
#("dashcam", "dashcam3-staging"),
#("dashcam_test", "dashcam3-staging"),
]
for name, branch in installers:
d = {'BRANCH': f"'\"{branch}\"'"}
if "internal" in name:
d['INTERNAL'] = "1"
import requests
r = requests.get("https://github.com/commaci2.keys")
r.raise_for_status()
d['SSH_KEYS'] = f'\\"{r.text.strip()}\\"'
qt_env.Program(f"qt/setup/installer_{name}", ["qt/setup/installer.cc"], LIBS=qt_libs, CPPDEFINES=d)
import requests
r = requests.get("https://github.com/commaci2.keys")
r.raise_for_status()
d['SSH_KEYS'] = f'\\"{r.text.strip()}\\"'
qt_env.Program(f"qt/setup/installer_{name}", ["qt/setup/installer.cc"], LIBS=qt_libs, CPPDEFINES=d)

View File

@ -1,125 +0,0 @@
#include <math.h>
#include <stdlib.h>
#include <atomic>
#include "common/swaglog.h"
#include "common/timing.h"
#include "android/sl_sound.hpp"
#define LogOnError(func, msg) \
if ((func) != SL_RESULT_SUCCESS) { LOGW(msg); }
#define ReturnOnError(func, msg) \
if ((func) != SL_RESULT_SUCCESS) { LOGW(msg); return false; }
struct SLSound::Player {
SLObjectItf player;
SLPlayItf playItf;
std::atomic<int> repeat;
};
SLSound::SLSound() {
if (!init()){
throw std::runtime_error("Failed to initialize sound");
}
}
bool SLSound::init() {
SLEngineOption engineOptions[] = {{SL_ENGINEOPTION_THREADSAFE, SL_BOOLEAN_TRUE}};
const SLInterfaceID ids[1] = {SL_IID_VOLUME};
const SLboolean req[1] = {SL_BOOLEAN_FALSE};
SLEngineItf engineInterface = NULL;
ReturnOnError(slCreateEngine(&engine_, 1, engineOptions, 0, NULL, NULL), "Failed to create OpenSL engine");
ReturnOnError((*engine_)->Realize(engine_, SL_BOOLEAN_FALSE), "Failed to realize OpenSL engine");
ReturnOnError((*engine_)->GetInterface(engine_, SL_IID_ENGINE, &engineInterface), "Failed to get OpenSL engine interface");
ReturnOnError((*engineInterface)->CreateOutputMix(engineInterface, &outputMix_, 1, ids, req), "Failed to create output mix");
ReturnOnError((*outputMix_)->Realize(outputMix_, SL_BOOLEAN_FALSE), "Failed to realize output mix");
for (auto &kv : sound_map) {
SLDataLocator_URI locUri = {SL_DATALOCATOR_URI, (SLchar *)kv.second.first};
SLDataFormat_MIME formatMime = {SL_DATAFORMAT_MIME, NULL, SL_CONTAINERTYPE_UNSPECIFIED};
SLDataSource audioSrc = {&locUri, &formatMime};
SLDataLocator_OutputMix outMix = {SL_DATALOCATOR_OUTPUTMIX, outputMix_};
SLDataSink audioSnk = {&outMix, NULL};
SLObjectItf player = NULL;
SLPlayItf playItf = NULL;
ReturnOnError((*engineInterface)->CreateAudioPlayer(engineInterface, &player, &audioSrc, &audioSnk, 0, NULL, NULL), "Failed to create audio player");
ReturnOnError((*player)->Realize(player, SL_BOOLEAN_FALSE), "Failed to realize audio player");
ReturnOnError((*player)->GetInterface(player, SL_IID_PLAY, &playItf), "Failed to get player interface");
ReturnOnError((*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PAUSED), "Failed to initialize playstate to SL_PLAYSTATE_PAUSED");
player_[kv.first] = new SLSound::Player{player, playItf};
}
return true;
}
void SLAPIENTRY slplay_callback(SLPlayItf playItf, void *context, SLuint32 event) {
SLSound::Player *s = reinterpret_cast<SLSound::Player *>(context);
if (event == SL_PLAYEVENT_HEADATEND && s->repeat != 0) {
if (s->repeat > 0) --s->repeat;
(*playItf)->SetPlayState(playItf, SL_PLAYSTATE_STOPPED);
(*playItf)->SetMarkerPosition(playItf, 0);
(*playItf)->SetPlayState(playItf, SL_PLAYSTATE_PLAYING);
}
}
bool SLSound::play(AudibleAlert alert) {
if (currentSound_ != AudibleAlert::NONE) {
stop();
}
auto player = player_.at(alert);
SLPlayItf playItf = player->playItf;
int loops = sound_map[alert].second;
player->repeat = loops > 0 ? loops - 1 : loops;
if (player->repeat != 0) {
ReturnOnError((*playItf)->RegisterCallback(playItf, slplay_callback, player), "Failed to register callback");
ReturnOnError((*playItf)->SetCallbackEventsMask(playItf, SL_PLAYEVENT_HEADATEND), "Failed to set callback event mask");
}
// Reset the audio player
ReturnOnError((*playItf)->ClearMarkerPosition(playItf), "Failed to clear marker position");
uint32_t states[] = {SL_PLAYSTATE_PAUSED, SL_PLAYSTATE_STOPPED, SL_PLAYSTATE_PLAYING};
for (auto state : states) {
ReturnOnError((*playItf)->SetPlayState(playItf, state), "Failed to set SL_PLAYSTATE_PLAYING");
}
currentSound_ = alert;
return true;
}
void SLSound::stop() {
if (currentSound_ != AudibleAlert::NONE) {
auto player = player_.at(currentSound_);
player->repeat = 0;
LogOnError((*(player->playItf))->SetPlayState(player->playItf, SL_PLAYSTATE_PAUSED), "Failed to set SL_PLAYSTATE_PAUSED");
currentSound_ = AudibleAlert::NONE;
}
}
void SLSound::setVolume(int volume) {
if (last_volume_ == volume) return;
double current_time = nanos_since_boot();
if ((current_time - last_set_volume_time_) > (5 * (1e+9))) { // 5s timeout on updating the volume
char volume_change_cmd[64];
snprintf(volume_change_cmd, sizeof(volume_change_cmd), "service call audio 3 i32 3 i32 %d i32 1 &", volume);
system(volume_change_cmd);
last_volume_ = volume;
last_set_volume_time_ = current_time;
}
}
SLSound::~SLSound() {
for (auto &kv : player_) {
(*(kv.second->player))->Destroy(kv.second->player);
delete kv.second;
}
if (outputMix_) {
(*outputMix_)->Destroy(outputMix_);
}
if (engine_) {
(*engine_)->Destroy(engine_);
}
}

View File

@ -1,26 +0,0 @@
#pragma once
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include "sound.hpp"
class SLSound : public Sound {
public:
SLSound();
~SLSound();
bool play(AudibleAlert alert);
void stop();
void setVolume(int volume);
private:
bool init();
SLObjectItf engine_ = nullptr;
SLObjectItf outputMix_ = nullptr;
int last_volume_ = 0;
double last_set_volume_time_ = 0.;
AudibleAlert currentSound_ = AudibleAlert::NONE;
struct Player;
std::map<AudibleAlert, Player *> player_;
friend void SLAPIENTRY slplay_callback(SLPlayItf playItf, void *context, SLuint32 event);
};

View File

@ -1,77 +0,0 @@
CC = clang
CXX = clang++
ROOT_DIR = ../../..
PHONELIBS = $(ROOT_DIR)/phonelibs
COMMON = $(ROOT)/selfdrive/common
WARN_FLAGS = -Werror=implicit-function-declaration \
-Werror=incompatible-pointer-types \
-Werror=int-conversion \
-Werror=return-type \
-Werror=format-extra-args
CFLAGS = -std=gnu11 -fPIC -O2 $(WARN_FLAGS)
CXXFLAGS = -std=c++1z -fPIC -O2 $(WARN_FLAGS)
NANOVG_FLAGS = -I$(PHONELIBS)/nanovg
OPENGL_LIBS = -lGLESv3
FRAMEBUFFER_LIBS = -lutils -lgui -lEGL
OBJS = spinner.o \
$(COMMON)/framebuffer.o \
$(COMMON)/util.o \
$(PHONELIBS)/nanovg/nanovg.o \
$(COMMON)/spinner.o \
opensans_semibold.o \
img_spinner_track.o \
img_spinner_comma.o
DEPS := $(OBJS:.o=.d)
.PHONY: all
all: spinner
spinner: $(OBJS)
@echo "[ LINK ] $@"
$(CXX) -fPIC -o '$@' $^ \
-s \
$(FRAMEBUFFER_LIBS) \
-L/system/vendor/lib64 \
$(OPENGL_LIBS) \
-lm -llog
$(COMMON)/framebuffer.o: $(COMMON)/framebuffer.cc
@echo "[ CXX ] $@"
$(CXX) $(CXXFLAGS) -MMD \
-I$(PHONELIBS)/android_frameworks_native/include \
-I$(PHONELIBS)/android_system_core/include \
-I$(PHONELIBS)/android_hardware_libhardware/include \
-c -o '$@' '$<'
opensans_semibold.o: $(ROOT_DIR)/selfdrive/assets/fonts/opensans_semibold.ttf
@echo "[ bin2o ] $@"
cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)'
img_spinner_track.o: $(ROOT_DIR)/selfdrive/assets/img_spinner_track.png
@echo "[ bin2o ] $@"
cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)'
img_spinner_comma.o: $(ROOT_DIR)/selfdrive/assets/img_spinner_comma.png
@echo "[ bin2o ] $@"
cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)'
%.o: %.c
@echo "[ CC ] $@"
$(CC) $(CFLAGS) -MMD \
-I../.. \
$(NANOVG_FLAGS) \
-c -o '$@' '$<'
.PHONY: clean
clean:
rm -f spinner $(OBJS) $(DEPS)
-include $(DEPS)

Binary file not shown.

View File

@ -1,182 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <unistd.h>
#include <assert.h>
#include <ctype.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 "framebuffer.h"
#include "spinner.h"
#define SPINTEXT_LENGTH 128
// external resources linked in
extern const unsigned char _binary_opensans_semibold_ttf_start[];
extern const unsigned char _binary_opensans_semibold_ttf_end[];
extern const unsigned char _binary_img_spinner_track_png_start[];
extern const unsigned char _binary_img_spinner_track_png_end[];
extern const unsigned char _binary_img_spinner_comma_png_start[];
extern const unsigned char _binary_img_spinner_comma_png_end[];
bool stdin_input_available() {
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 0;
fd_set fds;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
select(STDIN_FILENO+1, &fds, NULL, NULL, &timeout);
return (FD_ISSET(0, &fds));
}
int main(int argc, char** argv) {
bool draw_progress = false;
float progress_val = 0.0;
char spintext[SPINTEXT_LENGTH];
spintext[0] = 0;
const char* spintext_arg = NULL;
if (argc >= 2) {
strncpy(spintext, argv[1], SPINTEXT_LENGTH);
}
// spinner
int fb_w, fb_h;
FramebufferState *fb = framebuffer_init("spinner", 0x00001000, false,
&fb_w, &fb_h);
assert(fb);
framebuffer_set_power(fb, HWC_POWER_MODE_NORMAL);
NVGcontext *vg = nvgCreateGLES3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
assert(vg);
int font = nvgCreateFontMem(vg, "Bold", (unsigned char*)_binary_opensans_semibold_ttf_start, _binary_opensans_semibold_ttf_end-_binary_opensans_semibold_ttf_start, 0);
assert(font >= 0);
int spinner_img = nvgCreateImageMem(vg, 0, (unsigned char*)_binary_img_spinner_track_png_start, _binary_img_spinner_track_png_end - _binary_img_spinner_track_png_start);
assert(spinner_img >= 0);
int spinner_img_s = 360;
int spinner_img_x = ((fb_w/2)-(spinner_img_s/2));
int spinner_img_y = 260;
int spinner_img_xc = (fb_w/2);
int spinner_img_yc = (fb_h/2)-100;
int spinner_comma_img = nvgCreateImageMem(vg, 0, (unsigned char*)_binary_img_spinner_comma_png_start, _binary_img_spinner_comma_png_end - _binary_img_spinner_comma_png_start);
assert(spinner_comma_img >= 0);
for (int cnt = 0; ; cnt++) {
// Check stdin for new text
if (stdin_input_available()){
fgets(spintext, SPINTEXT_LENGTH, stdin);
spintext[strcspn(spintext, "\n")] = 0;
// Check if number (update progress bar)
size_t len = strlen(spintext);
bool is_number = len > 0;
for (int i = 0; i < len; i++){
if (!isdigit(spintext[i])){
is_number = false;
break;
}
}
if (is_number) {
progress_val = (float)(atoi(spintext)) / 100.0;
progress_val = fmin(1.0, progress_val);
progress_val = fmax(0.0, progress_val);
}
draw_progress = is_number;
}
glClearColor(0.1, 0.1, 0.1, 1.0);
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
nvgBeginFrame(vg, fb_w, fb_h, 1.0f);
// background
nvgBeginPath(vg);
NVGpaint bg = nvgLinearGradient(vg, fb_w, 0, fb_w, fb_h,
nvgRGBA(0, 0, 0, 175), nvgRGBA(0, 0, 0, 255));
nvgFillPaint(vg, bg);
nvgRect(vg, 0, 0, fb_w, fb_h);
nvgFill(vg);
// spin track
nvgSave(vg);
nvgTranslate(vg, spinner_img_xc, spinner_img_yc);
nvgRotate(vg, (3.75*M_PI * cnt/120.0));
nvgTranslate(vg, -spinner_img_xc, -spinner_img_yc);
NVGpaint spinner_imgPaint = nvgImagePattern(vg, spinner_img_x, spinner_img_y,
spinner_img_s, spinner_img_s, 0, spinner_img, 0.6f);
nvgBeginPath(vg);
nvgFillPaint(vg, spinner_imgPaint);
nvgRect(vg, spinner_img_x, spinner_img_y, spinner_img_s, spinner_img_s);
nvgFill(vg);
nvgRestore(vg);
// comma
NVGpaint comma_imgPaint = nvgImagePattern(vg, spinner_img_x, spinner_img_y,
spinner_img_s, spinner_img_s, 0, spinner_comma_img, 1.0f);
nvgBeginPath(vg);
nvgFillPaint(vg, comma_imgPaint);
nvgRect(vg, spinner_img_x, spinner_img_y, spinner_img_s, spinner_img_s);
nvgFill(vg);
if (draw_progress){
// draw progress bar
int progress_width = 1000;
int progress_x = fb_w/2-progress_width/2;
int progress_y = 775;
int progress_height = 25;
NVGpaint paint = nvgBoxGradient(
vg, progress_x + 1, progress_y + 1,
progress_width - 2, progress_height, 3, 4, nvgRGB(27, 27, 27), nvgRGB(27, 27, 27));
nvgBeginPath(vg);
nvgRoundedRect(vg, progress_x, progress_y, progress_width, progress_height, 12);
nvgFillPaint(vg, paint);
nvgFill(vg);
int bar_pos = ((progress_width - 2) * progress_val);
paint = nvgBoxGradient(
vg, progress_x, progress_y,
bar_pos+1.5f, progress_height-1, 3, 4,
nvgRGB(245, 245, 245), nvgRGB(105, 105, 105));
nvgBeginPath(vg);
nvgRoundedRect(
vg, progress_x+1, progress_y+1,
bar_pos, progress_height-2, 12);
nvgFillPaint(vg, paint);
nvgFill(vg);
} else {
// message
nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_TOP);
nvgFontSize(vg, 96.0f);
nvgText(vg, fb_w/2, (fb_h*2/3)+24, spintext, NULL);
}
nvgEndFrame(vg);
framebuffer_swap(fb);
assert(glGetError() == GL_NO_ERROR);
}
return 0;
}

View File

@ -1,64 +0,0 @@
CC = clang
CXX = clang++
PHONELIBS = ../../../../phonelibs
COMMON = ../../../common
WARN_FLAGS = -Werror=implicit-function-declaration \
-Werror=incompatible-pointer-types \
-Werror=int-conversion \
-Werror=return-type \
-Werror=format-extra-args
CFLAGS = -std=gnu11 -fPIC -O2 $(WARN_FLAGS)
CXXFLAGS = -std=c++1z -fPIC -O2 $(WARN_FLAGS)
NANOVG_FLAGS = -I$(PHONELIBS)/nanovg
OPENGL_LIBS = -lGLESv3
FRAMEBUFFER_LIBS = -lutils -lgui -lEGL
OBJS = text.o \
$(COMMON)/framebuffer.o \
$(COMMON)/util.o \
$(COMMON)/touch.o \
$(PHONELIBS)/nanovg/nanovg.o \
opensans_regular.o \
DEPS := $(OBJS:.o=.d)
.PHONY: all
all: text
text: $(OBJS)
@echo "[ LINK ] $@"
$(CXX) -fPIC -o '$@' $^ \
-s \
$(FRAMEBUFFER_LIBS) \
-L/system/vendor/lib64 \
$(OPENGL_LIBS) \
-lm -llog
opensans_regular.o: ../../../assets/fonts/opensans_regular.ttf
@echo "[ bin2o ] $@"
cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)'
%.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) \
-c -o '$@' '$<'
.PHONY: clean
clean:
rm -f text $(OBJS) $(DEPS)
-include $(DEPS)

Binary file not shown.

View File

@ -1,133 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <unistd.h>
#include <assert.h>
#include <memory>
#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 "common/framebuffer.h"
#include "common/touch.h"
#define COLOR_WHITE nvgRGBA(255, 255, 255, 255)
#define MAX_TEXT_SIZE 2048
extern const uint8_t bin_opensans_regular[] asm("_binary_opensans_regular_ttf_start");
extern const uint8_t *bin_opensans_regular_end asm("_binary_opensans_regular_ttf_end");
int main(int argc, char** argv) {
int err;
// spinner
int fb_w, fb_h;
std::unique_ptr<FrameBuffer> fb = std::make_unique<FrameBuffer>("text", 0x00001000, false,
&fb_w, &fb_h);
assert(fb);
NVGcontext *vg = nvgCreateGLES3(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
assert(vg);
int font = nvgCreateFontMem(vg, "regular", (unsigned char*)bin_opensans_regular, (bin_opensans_regular_end - bin_opensans_regular), 0);
assert(font >= 0);
// Awake
fb->set_power(HWC_POWER_MODE_NORMAL);
set_brightness(255);
glClearColor(0.1, 0.1, 0.1, 1.0);
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
nvgBeginFrame(vg, fb_w, fb_h, 1.0f);
// background
nvgBeginPath(vg);
NVGpaint bg = nvgLinearGradient(vg, fb_w, 0, fb_w, fb_h,
nvgRGBA(0, 0, 0, 175), nvgRGBA(0, 0, 0, 255));
nvgFillPaint(vg, bg);
nvgRect(vg, 0, 0, fb_w, fb_h);
nvgFill(vg);
// Text
nvgFillColor(vg, COLOR_WHITE);
nvgFontSize(vg, 75.0f);
if (argc >= 2) {
float x = 150;
float y = 150;
// Copy text
char * text = (char *)malloc(MAX_TEXT_SIZE);
strncpy(text, argv[1], MAX_TEXT_SIZE);
float lineh;
nvgTextMetrics(vg, NULL, NULL, &lineh);
// nvgTextBox strips leading whitespace. We have to reimplement
char * next = strtok(text, "\n");
while (next != NULL){
nvgText(vg, x, y, next, NULL);
y += lineh;
next = strtok(NULL, "\n");
}
}
// Button
int b_x = 1500;
int b_y = 800;
int b_w = 300;
int b_h = 150;
nvgBeginPath(vg);
nvgFillColor(vg, nvgRGBA(8, 8, 8, 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, "Exit", NULL);
nvgBeginPath(vg);
nvgStrokeColor(vg, nvgRGBA(255, 255, 255, 50));
nvgStrokeWidth(vg, 5);
nvgRoundedRect(vg, b_x, b_y, b_w, b_h, 20);
nvgStroke(vg);
// Draw to screen
nvgEndFrame(vg);
fb->swap();
assert(glGetError() == GL_NO_ERROR);
// Wait for button
TouchState touch;
touch_init(&touch);
while (true){
int touch_x = -1, touch_y = -1;
int res = touch_poll(&touch, &touch_x, &touch_y, 0);
if (res){
if (touch_x > b_x && touch_x < b_x + b_w){
if (touch_y > b_y && touch_y < b_y + b_h){
return 1;
}
}
}
usleep(1000000 / 60);
}
return 0;
}

View File

@ -1,191 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/resource.h>
#include <algorithm>
#include "common/framebuffer.h"
#include "common/util.h"
#include "common/params.h"
#include "common/swaglog.h"
#include "common/touch.h"
#include "common/watchdog.h"
#include "ui.hpp"
#include "paint.hpp"
#include "android/sl_sound.hpp"
ExitHandler do_exit;
static void ui_set_brightness(UIState *s, int brightness) {
static int last_brightness = -1;
if (last_brightness != brightness && (s->awake || brightness == 0)) {
if (set_brightness(brightness)) {
last_brightness = brightness;
}
}
}
static void handle_display_state(UIState *s, FrameBuffer *fb, bool user_input) {
static int awake_timeout = 0;
constexpr float accel_samples = 5*UI_FREQ;
static float accel_prev = 0., gyro_prev = 0.;
bool should_wake = s->scene.started || s->scene.ignition || user_input;
if (!should_wake) {
// tap detection while display is off
bool accel_trigger = abs(s->scene.accel_sensor - accel_prev) > 0.2;
bool gyro_trigger = abs(s->scene.gyro_sensor - gyro_prev) > 0.15;
should_wake = accel_trigger && gyro_trigger;
gyro_prev = s->scene.gyro_sensor;
accel_prev = (accel_prev * (accel_samples - 1) + s->scene.accel_sensor) / accel_samples;
}
// determine desired state
if (should_wake) {
awake_timeout = 30*UI_FREQ;
} else if (awake_timeout > 0){
--awake_timeout;
should_wake = true;
}
// handle state transition
if (s->awake != should_wake) {
s->awake = should_wake;
int display_mode = s->awake ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
LOGW("setting display mode %d", display_mode);
fb->set_power(display_mode);
if (s->awake) {
system("service call window 18 i32 1");
}
}
}
static void handle_vision_touch(UIState *s, int touch_x, int touch_y) {
if (s->scene.started && (touch_x >= s->viz_rect.x - bdr_s)
&& (s->active_app != cereal::UiLayoutState::App::SETTINGS)) {
if (!s->scene.driver_view) {
s->sidebar_collapsed = !s->sidebar_collapsed;
} else {
Params().write_db_value("IsDriverViewEnabled", "0", 1);
}
}
}
static void handle_sidebar_touch(UIState *s, int touch_x, int touch_y) {
if (!s->sidebar_collapsed && touch_x <= sbr_w) {
if (settings_btn.ptInRect(touch_x, touch_y)) {
s->active_app = cereal::UiLayoutState::App::SETTINGS;
} else if (home_btn.ptInRect(touch_x, touch_y)) {
if (s->scene.started) {
s->active_app = cereal::UiLayoutState::App::NONE;
s->sidebar_collapsed = true;
} else {
s->active_app = cereal::UiLayoutState::App::HOME;
}
}
}
}
static void update_offroad_layout_state(UIState *s, PubMaster *pm) {
static int timeout = 0;
static bool prev_collapsed = false;
static cereal::UiLayoutState::App prev_app = cereal::UiLayoutState::App::NONE;
if (timeout > 0) {
timeout--;
}
if (prev_collapsed != s->sidebar_collapsed || prev_app != s->active_app || timeout == 0) {
MessageBuilder msg;
auto layout = msg.initEvent().initUiLayoutState();
layout.setActiveApp(s->active_app);
layout.setSidebarCollapsed(s->sidebar_collapsed);
pm->send("offroadLayout", msg);
LOGD("setting active app to %d with sidebar %d", (int)s->active_app, s->sidebar_collapsed);
prev_collapsed = s->sidebar_collapsed;
prev_app = s->active_app;
timeout = 2 * UI_FREQ;
}
}
int main(int argc, char* argv[]) {
setpriority(PRIO_PROCESS, 0, -14);
SLSound sound;
UIState uistate = {};
UIState *s = &uistate;
FrameBuffer fb = FrameBuffer("ui", 0, true, &s->fb_w, &s->fb_h);
ui_init(s);
s->sound = &sound;
TouchState touch = {0};
touch_init(&touch);
handle_display_state(s, &fb, true);
PubMaster *pm = new PubMaster({"offroadLayout"});
// light sensor scaling and volume params
float brightness_b = 0, brightness_m = 0;
int result = read_param(&brightness_b, "BRIGHTNESS_B", true);
result += read_param(&brightness_m, "BRIGHTNESS_M", true);
if (result != 0) {
brightness_b = 10.0;
brightness_m = 2.6;
write_param_float(brightness_b, "BRIGHTNESS_B", true);
write_param_float(brightness_m, "BRIGHTNESS_M", true);
}
float smooth_brightness = brightness_b;
const int MIN_VOLUME = 12;
const int MAX_VOLUME = 15;
s->sound->setVolume(MIN_VOLUME);
while (!do_exit) {
watchdog_kick();
if (!s->scene.started) {
util::sleep_for(50);
}
double u1 = millis_since_boot();
ui_update(s);
// poll for touch events
int touch_x = -1, touch_y = -1;
int touched = touch_poll(&touch, &touch_x, &touch_y, 0);
if (touched == 1) {
handle_sidebar_touch(s, touch_x, touch_y);
handle_vision_touch(s, touch_x, touch_y);
}
// Don't waste resources on drawing in case screen is off
handle_display_state(s, &fb, touched == 1);
if (!s->awake) {
continue;
}
// up one notch every 5 m/s
s->sound->setVolume(fmin(MAX_VOLUME, MIN_VOLUME + s->scene.car_state.getVEgo() / 5));
// set brightness
float clipped_brightness = fmin(512, (s->scene.light_sensor*brightness_m) + brightness_b);
smooth_brightness = fmin(255, clipped_brightness * 0.01 + smooth_brightness * 0.99);
ui_set_brightness(s, (int)smooth_brightness);
update_offroad_layout_state(s, pm);
ui_draw(s);
double u2 = millis_since_boot();
if (!s->scene.driver_view && (u2-u1 > 66)) {
// warn on sub 15fps
LOGW("slow frame(%llu) time: %.2f", (s->sm)->frame, u2-u1);
}
fb.swap();
}
handle_display_state(s, &fb, true);
delete s->sm;
delete pm;
return 0;
}

Binary file not shown.

Binary file not shown.

View File

@ -5,6 +5,7 @@
#include <QApplication>
#include "qt_window.hpp"
#include "selfdrive/hardware/hw.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
@ -21,7 +22,7 @@ int main(int argc, char *argv[]) {
#ifdef __aarch64__
btn->setText("Reboot");
QObject::connect(btn, &QPushButton::released, [=]() {
std::system("sudo reboot");
Hardware::reboot();
});
#else
btn->setText("Exit");
@ -32,6 +33,7 @@ int main(int argc, char *argv[]) {
window.setLayout(layout);
window.setStyleSheet(R"(
* {
outline: none;
color: white;
background-color: black;
font-size: 60px;

Binary file not shown.

Binary file not shown.

View File

@ -1,12 +1,10 @@
#!/bin/sh
if [ -f /EON ]; then
export LD_LIBRARY_PATH="/system/lib64:$LD_LIBRARY_PATH"
exec ./android/spinner/spinner "$1"
else
if [ -f /TICI ] && [ ! -f qt/spinner ]; then
cp qt/spinner_aarch64 qt/spinner
fi
exec ./qt/spinner "$1"
if [ -f /EON ] && [ ! -f qt/spinner ]; then
cp qt/spinner_aarch64 qt/spinner
elif [ -f /TICI ] && [ ! -f qt/spinner ]; then
cp qt/spinner_larch64 qt/spinner
fi
export LD_LIBRARY_PATH="/system/lib64:$LD_LIBRARY_PATH"
exec ./qt/spinner "$1"

View File

@ -1,12 +1,10 @@
#!/bin/sh
if [ -f /EON ]; then
export LD_LIBRARY_PATH="/system/lib64:$LD_LIBRARY_PATH"
exec ./android/text/text "$1"
else
if [ -f /TICI ] && [ ! -f qt/text ]; then
cp qt/text_aarch64 qt/text
fi
exec ./qt/text "$1"
if [ -f /EON ] && [ ! -f qt/text ]; then
cp qt/text_aarch64 qt/text
elif [ -f /TICI ] && [ ! -f qt/text ]; then
cp qt/text_larch64 qt/text
fi
export LD_LIBRARY_PATH="/system/lib64:$LD_LIBRARY_PATH"
exec ./qt/text "$1"