Ubuntu TouchずAndroidの盞互䜜甚の原則を孊ぶ



こんにちは、Habr。



数か月前、 Ubuntu TouchをAllwinner A10プラットフォヌムに移怍しおいたしたが、

その過皋で私は蚘念品ずしおメモを取った。 今、私の意芋では、Ubuntu Touchが最終的にMirグラフィックサヌバヌなどに移行するたで、それらは䟝然ずしお関連しおいたす。



この蚘事は、興味のある人がUTずの芪密な関係を始めるための出発点を芋぀けるのに圹立ちたす。



プレれンテヌションのスタむルは技術的なものずはほど遠いですが、気にしない堎合は、

猫に誘いたす。





はじめに



libhybrisずは


libhybrisは、ラむブラリをBionicナヌザヌスペヌスからGlibcナヌザヌスペヌスにロヌドできるレむダヌで、䞀郚の文字をGlibcのオプションでオンザフラむで眮き換えたす。 簡単に蚀えば、この゜リュヌションを䜿甚するず、Linux空間でAndroid専甚のラむブラリを䜿甚できたす。 もちろん、最倧のメリットは、補造元がAndroid専甚に䜜成した独自のGPUドラむバヌを䜿甚できるこずです。



Surfaceflingerずは


surfaceflinger-ネむティブAndroidサヌビス、グラフィックレむダヌの耇合マネヌゞャヌ。







バむンダヌIPCずSurfaceFlingerの詳现 





Ubuntu touch


Ubuntu Touch Developer Preview自䜓はAndroidに基づいおおり、ハヌドりェアを操䜜するために必芁なサヌビスを借りおいたす。 䟝存関係の䞀般的な抂芁は、 Ubuntu Touch PortingたたはOpenNetのメモにありたす。



基本オペレヌティングシステムずしお、通垞のAndroid JB 4.2が䜿甚されるか、むしろCyagenMod-10.1 CMサブプロゞェクトのリポゞトリはphablet.ubuntu.com/gitweb です。 dalvikずjavaに関連するものはすべお削陀されたした-システムサヌビスずHALで構成されるネむティブ郚分のみが残りたす。 必芁に応じお、 AOSP 4.1を䜿甚できたすが、4.1のネむティブAPIに適応する準備ができおおり、ドキュメントや仕様によっおカバヌされおおらず、リリヌスごずに異なりたす。



UTコンポヌネントはchrootにあり、自己蚘述されたuchrootナヌティリティが䜿甚されたす 、抜粋

static int ubuntum(void *a) { /* Chroot */ chroot("/data/ubuntu"); chdir("/"); /* Set basic env variables */ char *const envp[8] = { "container=aal", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "SHELL=/bin/bash", "HOME=/root", "USER=root", "USERNAME=root", "LOGNAME=root", NULL }; /* Exec shell */ execle("/sbin/init", "/sbin/init", "--verbose", NULL, envp); return 0; }
      
      





Android環境ずUbuntuのchroot環境間の盞互䜜甚には、 libhybrisメカニズムが䜿甚されたす。





Ubuntu Touchコンポヌネント



さたざたなUTコンポヌネントからのスヌプは〜phablet-teamランチパッドリポゞトリで芋るこずができたす。

Androidデバむスのプラットフォヌムを担圓する次の2぀のコンポヌネントに関心がありたす。



最新の゜ヌスコヌドをダりンロヌドしたす。

 bzr branch lp:platform-api bzr branch lp:qtubuntu
      
      







Ubuntu Platform API


UbuntuプラットフォヌムAPIは、 プラットフォヌムの機胜Androidを䜿甚しお基本操䜜を実行するための䜎レベルAPIです。



メ゜ッドの䟋



doc / mainpage.mdドキュメントファむルから、 platform-api゜ヌスツリヌは2぀の郚分に分割できるこずがわかりたす。



そしお、このAPIを䜿甚する際にサヌドパヌティの開発者が信頌できる唯䞀のものは、

/ ubuntu / applicationディレクトリを含み 、他のすべおのものは時間の経過ずずもに倉化するず予想されたす。



debian / controlファむルから次のこずを孊びたす

 Package: libplatform-api1-hybris Depends: libhybris Description: Hybris implementation of the Platform API (runtime) This package provides the hybris implementation of the Platform API. The produced library should be used via libhybris, to communicate with the Android userspace, which is where the Ubuntu Application Manager lives.
      
      





そう、぀たり、 Android / hybris / Android.mkで刀断するず、プラットフォヌムAPI実装は、ネむティブAndroid ラむブラリずのリンクを持぀libubuntu_application_apiラむブラリずしお組み立おられ、Androidナヌザヌスペヌスに配眮されたす。

 LOCAL_SRC_FILES := \ ubuntu_application_api_for_hybris.cpp \ ubuntu_application_gps_for_hybris.cpp \ ubuntu_application_sensors_for_hybris.cpp \ ../default/default_ubuntu_application_sensor.cpp \ ../default/default_ubuntu_application_ui.cpp \ ../default/default_ubuntu_ui.cpp \ application_manager.cpp LOCAL_MODULE := libubuntu_application_api LOCAL_SHARED_LIBRARIES := \ libandroidfw \ libbinder \ libutils \ libgui \ libEGL \ libGLESv2 \ libhardware \ libhardware_legacy
      
      





platform-api / src / androidディレクトリは無人のたたにされたした。詳现に怜蚎したす。 CMakeLists.txtファむルの存圚から刀断するず、glibcのアセンブリは既に進行䞭です。



コヌドを含む1぀のファむル-ubuntu_application_api.cppがありたす。

 extern void *android_dlopen(const char *filename, int flag); extern void *android_dlsym(void *handle, const char *symbol);
      
      



-libhybrisプロシヌゞャを䜿甚しお、Androidナヌザヌ空間から共有ラむブラリから文字を動的にロヌドしたす。



 struct Bridge { static const char* path_to_library() { return "/system/lib/libubuntu_application_api.so"; } Bridge() : lib_handle(android_dlopen(path_to_library(), RTLD_LAZY)) { assert(lib_handle && "Error loading ubuntu_application_api"); } ....... void* resolve_symbol(const char* symbol) const { return android_dlsym(lib_handle, symbol); } void* lib_handle; };
      
      



-libubuntu_application_api.soからキャラクタヌをロヌドするためのシンプルなブリッゞ。これはネむティブAndroidサヌビスず連携し 、 android / hybris / Android.mkを䜿甚しお最近「粟神的に」組み立おたした 。



 #define IMPLEMENT_VOID_FUNCTION3(symbol, arg1, arg2, arg3) \ void symbol(arg1 _1, arg2 _2, arg3 _3) { \ static void (*f)(arg1, arg2, arg3) = NULL; \ DLSYM(&f, #symbol); \ f(_1, _2, _3); } ....... IMPLEMENT_VOID_FUNCTION2(ubuntu_application_ui_init, int, char**); IMPLEMENT_FUNCTION0(StageHint, ubuntu_application_ui_setup_get_stage_hint); IMPLEMENT_FUNCTION0(FormFactorHint, ubuntu_application_ui_setup_get_form_factor_hint); IMPLEMENT_VOID_FUNCTION1(ubuntu_application_ui_start_a_new_session, SessionCredentials*); IMPLEMENT_VOID_FUNCTION2(ubuntu_application_ui_set_clipboard_content, void*, size_t); .......
      
      



-libubuntu_application_api.soに実装されたAPI文字のラッパヌの束。



混乱を避けるために



開発者は、同じ名前のラむブラリを䜜成するこずで、宇宙の゚ントロピヌを枛らすこずにしたした。

merge-153874ディスカッションコンポヌネントの呜名に関する圌らの議論を芋るず、あなたの耳は消えおしたいたす。



Ubuntuアプリケヌションマネヌゞャヌ


platform-api / android / hybrisには、UbuntuプラットフォヌムAPIの実装に加えお、 ubuntuappmanagerの゜ヌスがありたす-Ubuntuアプリケヌションサヌビスは、Androidナヌザヌ空間に存圚し、 Android.mkから刀断しお、 libubuntu_application_apiを積極的に䜿甚し、Androidを介しおBinder IPCサヌビスず通信したす。

 LOCAL_SRC_FILES:= \ application_manager.cpp \ default_application_manager.cpp \ LOCAL_MODULE:= ubuntuappmanager LOCAL_MODULE_TAGS := optional LOCAL_SHARED_LIBRARIES := \ libbinder \ libinput \ libgui \ libskia \ libandroidfw \ libutils \ libEGL \ libGLESv2 \ libubuntu_application_api
      
      





default_application_manager.hを簡単に芋お、 倚数のアプリケヌションおよびセッション管理タスクを解決したす。

  void update_app_lists(); void binderDied(const android::wp<android::IBinder>& who); void register_a_surface(...); void request_fullscreen(...); int get_session_pid(const android::sp<android::IApplicationManagerSession>& session); void focus_running_session_with_id(int id); void unfocus_running_sessions(); int32_t query_snapshot_layer_for_session_with_id(int id); android::IApplicationManagerSession::SurfaceProperties query_surface_properties_for_session_id(int id); void switch_focused_application_locked(size_t index_of_next_focused_app); void switch_focus_to_next_application_locked(); void kill_focused_application_locked(); void start_a_new_session( int32_t session_type, int32_t stage_hint, const android::String8& app_name, const android::String8& desktop_file, const android::sp<android::IApplicationManagerSession>& session, int fd);
      
      





QtUbuntu


UbuntuプラットフォヌムAPIずQt / QMLアプリケヌション間の盞互䜜甚を担圓するUTの郚分を扱いたす。



Qt Platform Abstractionに慣れおいない堎合、芁するに、これは特別に䜜成されたQPAプラグむンを䜿甚しおQtアプリケヌションが起動されおいるプラ​​ットフォヌムから抜象化する機䌚です。



QPAプラグむンはcreatePlatformWindowなどの基本的なメ゜ッドを実装し、Qtアプリケヌションはりィンドりを䜜成するずきに、抜象化プラグむンのcreatePlatformWindowシンボルを䜿甚し、 そこからどこぞ行っおも吹き飛ばしたせん。



この堎合、UbuntuアプリケヌションAPIを操䜜するためのQPAプラグむンを扱いたす。

 ~/ubuntu/qtubuntu $ tree . ├── qtubuntu.pro ├── src │ ├── modules │ │ ├── application <------------------ QML plugin    │ │ │ ├── application.cc | Ubuntu Application Manager │ │ │ ├── application.h |  QtQuick │ │ │ ├── application.pro | │ │ │ ├── application_image.cc | │ │ │ ├── application_image.h | │ │ │ ├── application_list_model.cc | │ │ │ ├── application_list_model.h | │ │ │ ├── application_manager.cc | │ │ │ ├── application_manager.h | │ │ │ ├── application_window.cc | │ │ │ ├── application_window.h | │ │ │ ├── input_filter_area.cc | │ │ │ ├── input_filter_area.h | │ │ │ ├── logging.h | │ │ │ ├── plugin.cc | │ │ │ └── qmldir | │ │ ├── ---------------------------------- │ │ └── modules.pro │ ├── platforms │ │ ├── base │ │ ├── platforms.pro │ │ └── ubuntu <-------------- QPA   │ │ ├── clipboard.cc │ │ ├── clipboard.h │ │ ├── input.cc │ │ ├── input.h │ │ ├── integration.cc <--   `createPlatformWindow`  │ │ ├── integration.h │ │ ├── main.cc │ │ ├── screen.cc │ │ ├── screen.h │ │ ├── ubuntu.json │ │ ├── ubuntu.pro │ │ ├── window.cc │ │ └── window.h │ └── src.pro └── tests
      
      





ubuntu.proのコンテンツから刀断するず、プラットフォヌムはlibubuntu_application_api.soの glibcバヌゞョンずリンクしおいたす

integration.ccおよびwindow.ccで䜿甚されるプラットフォヌムAPIセットからの次のメ゜ッド呌び出しに泚意しおください。

 #include <ubuntu/application/ui/ubuntu_application_ui.h> ubuntu_application_ui_start_a_new_session(&credentials); ubuntu_application_ui_destroy_surface(surface_); ubuntu_application_ui_create_surface(&surface_, "QUbuntuWindow", geometry.width(), geometry.height(), static_cast<SurfaceRole>(role), flags, eventCallback, this); ubuntu_application_ui_move_surface_to(surface_, geometry.x(), geometry.y()); ubuntu_application_ui_request_fullscreen_for_surface(surface_); ubuntu_application_ui_move_surface_to(surface_, rect.x(), rect.y()); ubuntu_application_ui_resize_surface_to(surface_, rect.width(), rect.height()); ubuntu_application_ui_request_fullscreen_for_surface(surface_); ubuntu_application_ui_show_surface(surface_); ubuntu_application_ui_hide_surface(surface_);
      
      





これで、Qtアプリケヌションがりィンドりを䜜成する際に、 qubuntuプラットフォヌムのQPAからメ゜ッドを呌び出すこずが明らかになりたした-QUbuntuIntegration :: integration.ccファむルのcreatePlatformWindow 

 QPlatformWindow* QUbuntuIntegration::createPlatformWindow(QWindow* window) { ....... // Create the window. QPlatformWindow* platformWindow = new QUbuntuWindow(.......); ....... }
      
      





window.ccファむルのQUbuntuWindowコンストラクタヌを調べるず、 QUbuntuWindow :: createWindowメ゜ッドの呌び出しが芋぀かりたす。

 void QUbuntuWindow::createWindow() { ....... ubuntu_application_ui_create_surface( &surface_, "QUbuntuWindow", geometry.width(), geometry.height(), static_cast<SurfaceRole>(role), flags, eventCallback, this); ....... ubuntu_application_ui_move_surface_to(surface_, geometry.x(), geometry.y()); ....... }
      
      





これは非垞に簡略化されたコヌドですが、本質は明確です-libubuntu_application_api.soのglibcバヌゞョンで実装したUbuntuプラットフォヌムAPIが呌び出されたす 。これは、実際にはlibubuntu_application_api.soのバむオニックバヌゞョンぞのブリッゞです。 api / android 。



ゞャンプしおる



grepを䜿甚しお目的のファむルにゞャンプするず、 platform-api / android / default / default_ubuntu_application_ui.cppに移動したす。

 //   ubuntu_application_ui_create_surface ubuntu::application::ui::Surface::Ptr surface = session->create_surface(props, ubuntu::application::ui::input::Listener::Ptr(new CallbackEventListener(cb, ctx))); //   ubuntu_application_ui_move_surface_to auto s = static_cast<Holder<ubuntu::application::ui::Surface::Ptr>*>(surface); s->value->move_to(x, y);
      
      





人圢を開いお、 ubuntu :: application :: ui :: Sessionおよびそれに応じお、 ubuntu :: application :: ui :: Surfaceがどのように実装されおいるかを確認するこずは残りたす。 そしお、それらはこのファむルに実装されおいたす-ubuntu_application_api_for_hybris.cpp 

 namespace android { ....... struct Session : public ubuntu::application::ui::Session, public UbuntuSurface::Observer { ....... Session(.....) { ...... ubuntu::application::ui::Surface::Ptr create_surface( const ubuntu::application::ui::SurfaceProperties& props, const ubuntu::application::ui::input::Listener::Ptr& listener) { ....... // ,     .        UbuntuSurface UbuntuSurface* surface = new UbuntuSurface(client, client_channel, looper, props, listener,this); ....... // 100%   ,    UbuntuSurface return ubuntu::application::ui::Surface::Ptr(surface); .......
      
      





巻き戻し、 UbuntuSurfaceを芋぀けたす 。

 struct UbuntuSurface : public ubuntu::application::ui::Surface { ....... UbuntuSurface(const sp<SurfaceComposerClient>& client, .......) : ubuntu::application::ui::Surface(listener) { //    -    Android API surface_control = client->createSurface( String8(props.title), props.width, props.height, PIXEL_FORMAT_RGBA_8888, props.flags & .......); surface = surface_control->getSurface(); .......
      
      





android :: SurfaceControl型のオブゞェクトを取埗したす。これは、 android :: SurfaceComposerClient-> createSurfaceの呌び出しの結果です。

android :: SurfaceComposerClient  frameworks / native / libs / gui / Surface.cpp ぞのすべおの呌び出しは、サむズ倉曎、移動、レむダヌの順序の倉曎などを通過したす。



チェヌンに戻っお、QPAプラットフォヌムUbuntuで次のQtアプリケヌションを起動するず実際に䜕が起こるかを理解したす。



おわりに



私の意芋では、䞊蚘で説明したUbuntu TouchずAndroidの盞互䜜甚の原理は自絊自足であるため、この時点で自分を止めなければなりたせん。 䞊蚘のすべおずは別に、さらなる怜蚎が既に行われおいる堎合がありたす。 qmlsceneずubuntuappmanagerの盞互䜜甚の問題、 SurfaceFlingerおよびInputDispatcherサヌビスを䜿甚した入力制埡の原則、およびこの広範なトピックのコヌナヌからの他の質問は未解決のたたでした。 しかし、これはたったく異なる話です。



1週間埌、Firefox OSに電話が届きたす。



All Articles