Итак, задумывались ли вы, что происходит когда вы достаете из Context скажем ConnectivityManager? Как вы помните ConnectivityManager это класс, который позволяет отлеживать состояние сети. У него достаточно удобное API позволяющее узнать если ли сейчас сеть, повесить колбеки на это, короче все что связано с сетью. Получаем мы его вот так:
val connectivityManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
И вот если вдуматься в синтаксис, ну абсурд же происходит! Вроде достаем сервис, а получаем менеджер. Да и системный же сервис работает в другом процессе, что за дичь вообще? Сейчас все раскидаем. Наше приключение начинается с Context. Два основных факта про Context. Первый – Context это God object умеющий все на свете и вообще связующий класс через который мы общаемся с системой. Второй – сам по себе Context это абстрактный класс.
У Context куча наследников, в том числе основные компоненты: Application, Activity, Service и т.д. В Context 200 методов и реализовывать их в каждом наследнике, учитывая то, что они делают примерно одно и тоже, это сизифов труд. Поэтому разработчики сделали класс ContextImpl, который реализует основные методы. Вспоминаем шаблон декоратор. Activity наследует Context, после Activity переопределяет методы Context которые ей нужны, а все остальные методы просто вызывают методы класса ContextImpl. Аналогично и во всеми остальными наследниками Context.
Нас сейчас интересует конкретный метод Context getSystemService. Каждый раз при вызове этого метода он идет в SystemServiceRegistry, который по сути: Map<String, (Context) -> Any>. И getSystemService делает примерно вот что:
fun getSystemService(str:Stiring):Any { val fetcher = systemServiceRegistry[str] return fetcher(this) }
SystemServiceRegistry это класс, в котором огромный блок static наполняющий эту саму Map. Суть – есть имя сервиса и логика как его получить, обращаемся к SystemServiceRegistry по имени сервиса, и он нам его собирает. Точнее говоря, собирает не сам сервис, а некоторого клиента или менеджера который умеет работать с каким-то системным сервисом. Именно так мы и получаем ConnectivityManager, однако это только начало.
При старте системы, она запускает SystemServer, который в свою очередь запускает системные сервисы, прям все. Сервисов много, но нас сейчас интересует ConnectivityServiceInitializer. ConnectivityServiceInitializer это системный сервис, основная задача которого просто создать объект класса ConnectivityService и сохранить его у себя. Хоть ConnectivityService и называется сервисом, это просто обычный класс, в котором скрыта логика по общению с netd. С тем самым демоном о котором говорили ранее.
Если ты дочитал до сюда и все еще легко ставь❤️. В системе есть AIDL интерфейс с названием IConnectivityManager. ConnectivityService это Stub интерфейса IConnectivityManager. Или по другому, к ConnectivityService кто-то может стучаться через Binder и вызывать его методы из другого процесса. И этот кто-то ConnectivityManager, который при создании получает Proxy интерфейса IConnectivityManager. Получив proxy, можно вызывать методы ConnectivityManager, который крутится в ConnectivityServiceInitializer и имеющий доступ к netd, а тем самым к информации о сети.
Жестко, я понимаю сам офигивал от такой картины. Главное тут это то, что во многих аспектах работает связка Manager–Service. Складываем все части мозаики воедино получаем что, есть системные сервисы и есть всякие менеджеры которые мы получаем из Context. Через эти менеджеры мы можем общаться с системными сервисами и общение это происходит через Binder. Разумеется не все что мы получаем через getSystemService обязательно общается с каким-то системным сервисом. Есть например LayoutInflator который ни с кем не общается и просто создается как обычный объект в SystemServiceRegistry.
В этом посте описана суть на примере ConnectivityManager. Есть некоторые сервисы, которые построены сложнее, где по 10 слоев абстракций между менеджером и системным сервисом. Однако основа у всех одна.
Итак, задумывались ли вы, что происходит когда вы достаете из Context скажем ConnectivityManager? Как вы помните ConnectivityManager это класс, который позволяет отлеживать состояние сети. У него достаточно удобное API позволяющее узнать если ли сейчас сеть, повесить колбеки на это, короче все что связано с сетью. Получаем мы его вот так:
val connectivityManager = context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
И вот если вдуматься в синтаксис, ну абсурд же происходит! Вроде достаем сервис, а получаем менеджер. Да и системный же сервис работает в другом процессе, что за дичь вообще? Сейчас все раскидаем. Наше приключение начинается с Context. Два основных факта про Context. Первый – Context это God object умеющий все на свете и вообще связующий класс через который мы общаемся с системой. Второй – сам по себе Context это абстрактный класс.
У Context куча наследников, в том числе основные компоненты: Application, Activity, Service и т.д. В Context 200 методов и реализовывать их в каждом наследнике, учитывая то, что они делают примерно одно и тоже, это сизифов труд. Поэтому разработчики сделали класс ContextImpl, который реализует основные методы. Вспоминаем шаблон декоратор. Activity наследует Context, после Activity переопределяет методы Context которые ей нужны, а все остальные методы просто вызывают методы класса ContextImpl. Аналогично и во всеми остальными наследниками Context.
Нас сейчас интересует конкретный метод Context getSystemService. Каждый раз при вызове этого метода он идет в SystemServiceRegistry, который по сути: Map<String, (Context) -> Any>. И getSystemService делает примерно вот что:
fun getSystemService(str:Stiring):Any { val fetcher = systemServiceRegistry[str] return fetcher(this) }
SystemServiceRegistry это класс, в котором огромный блок static наполняющий эту саму Map. Суть – есть имя сервиса и логика как его получить, обращаемся к SystemServiceRegistry по имени сервиса, и он нам его собирает. Точнее говоря, собирает не сам сервис, а некоторого клиента или менеджера который умеет работать с каким-то системным сервисом. Именно так мы и получаем ConnectivityManager, однако это только начало.
При старте системы, она запускает SystemServer, который в свою очередь запускает системные сервисы, прям все. Сервисов много, но нас сейчас интересует ConnectivityServiceInitializer. ConnectivityServiceInitializer это системный сервис, основная задача которого просто создать объект класса ConnectivityService и сохранить его у себя. Хоть ConnectivityService и называется сервисом, это просто обычный класс, в котором скрыта логика по общению с netd. С тем самым демоном о котором говорили ранее.
Если ты дочитал до сюда и все еще легко ставь❤️. В системе есть AIDL интерфейс с названием IConnectivityManager. ConnectivityService это Stub интерфейса IConnectivityManager. Или по другому, к ConnectivityService кто-то может стучаться через Binder и вызывать его методы из другого процесса. И этот кто-то ConnectivityManager, который при создании получает Proxy интерфейса IConnectivityManager. Получив proxy, можно вызывать методы ConnectivityManager, который крутится в ConnectivityServiceInitializer и имеющий доступ к netd, а тем самым к информации о сети.
Жестко, я понимаю сам офигивал от такой картины. Главное тут это то, что во многих аспектах работает связка Manager–Service. Складываем все части мозаики воедино получаем что, есть системные сервисы и есть всякие менеджеры которые мы получаем из Context. Через эти менеджеры мы можем общаться с системными сервисами и общение это происходит через Binder. Разумеется не все что мы получаем через getSystemService обязательно общается с каким-то системным сервисом. Есть например LayoutInflator который ни с кем не общается и просто создается как обычный объект в SystemServiceRegistry.
В этом посте описана суть на примере ConnectivityManager. Есть некоторые сервисы, которые построены сложнее, где по 10 слоев абстракций между менеджером и системным сервисом. Однако основа у всех одна.
The initiatives announced by Perekopsky include monitoring the content in groups. According to the executive, posts identified as lacking context or as containing false information will be flagged as a potential source of disinformation. The content is then forwarded to Telegram's fact-checking channels for analysis and subsequent publication of verified information. With Bitcoin down 30% in the past week, some crypto traders have taken to Telegram to “voice” their feelings. bank east asia october 20 kowloon To upload a logo, click the Menu icon and select “Manage Channel.” In a new window, hit the Camera icon. Clear
from us