Android build device name

Как правильно идентифицировать Android-устройства

Всем привет! Если вам нужно создать уникальный и стабильный идентификатор Android-устройства для использования внутри приложения, то вы наверняка заметили тот хаос, который присутствует в документации и в ответах на stackoverflow. Давайте рассмотрим, как решить эту задачу в 2020 году. О том, где взять идентификатор, стойкий к переустановкам вашего приложения, и какие могут быть сложности в будущем — в этом кратком обзоре. Поехали!

Зачем нужна идентификация

В последнее время обсуждения конфиденциальности пользовательских данных стремительно набирают популярность. Возможно, это спровоцировано ростом выручки рекламных гигантов. Возможно, под этими обсуждениями скрывается обеспокоенность монополиями, которые идентифицируют пользователей и их устройства. Так, Apple, борясь со слежкой и ограничивая всем разработчикам использование IDFA, в то же самое время нисколько не ограничивает его себе. Что можно сказать точно: процесс идентификации пользователя приложения для разработчиков усложнился.

В задачах, опирающихся на идентификацию, встречаются: аналитика возвратов, персонализация контента и рекламы, предотвращение мошенничества.

Среди последних можно выделить несколько актуальных проблем:

Общие аккаунты в сервисах с платной подпиской или уникальным платным контентом. Только представьте сколько теряют сервисы вроде Netflix или Coursera от того, что пользователи заводят один аккаунт на нескольких человек.

Обе проблемы ведут либо к потере выручки, либо к репутационным потерям. Надежность их решения напрямую зависит от надежности идентификации устройств.

Основные способы идентификации

Использование аппаратных идентификаторов

Устаревший и нежизнеспособный в настоящее время способ. Google хорошо поработала над тем, чтобы закрыть доступ к ним, поскольку они не меняются даже после сброса к заводским настройкам. Среди таких идентификаторов:

В настоящее время они недоступны без явного запроса разрешений. Более того, если приложению нужно ими пользоваться, оно может не попасть в Play Market. Оно должно основным функционалом опираться на эти разрешения, иначе будут трудности с прохождением ревью. Поэтому сейчас эта опция доступна приложениям для работы со звонками или голосовым ассистентам.

Такие идентификаторы не меняются после сброса к заводским настройкам, и здесь кроется неочевидный недостаток: люди могут продавать свои устройства, и в таком случае идентификатор будет указывать на другого человека.

Генерация UUID с первым запуском

Данный способ схож с использованием cookie: создаем файл со сгенерированной строкой, сохраняем его в песочнице нашего приложения (например с помощью SharedPreferences), и используем как идентификатор. Недостаток тот же, что и у cookie — вся песочница удаляется вместе с приложением. Еще она может быть очищена пользователем явно из настроек.

При наличии у приложения разрешений к хранилищу вне песочницы можно сохранить идентификатор где-то на устройстве и постараться поискать его после переустановки. Будет ли в тот момент нужное разрешение у приложения — неизвестно. Этот идентификатор можно использовать как идентификатор установки приложения (app instance ID).

Использование идентификаторов, предоставляемых системой

В документации для разработчиков представлен идентификатор ANDROID_ID. Он уникален для каждой комбинации устройства, пользователя, и ключа, которым подписано приложение. До Android 8.0 идентификатор был общим для всех приложений, после — уникален только в рамках ключа подписи. Этот вариант в целом годится для идентификации пользователей в своих приложениях (которые подписаны вашим сертификатом).

Существует и менее известный способ получить идентификатор общий для всех приложений, независимо от сертификата подписи. При первичной настройке устройства (или после сброса к заводским) сервисы Google генерируют идентификатор. Вы не найдете о нем никакой информации в документации, но тем не менее можете попробовать код ниже, он будет работать (по состоянию на конец 2020 года).

Добавляем строчку в файл манифеста нужного модуля:

И вот так достаем идентификатор:

В коде происходит следующее: мы делаем запрос к данным из определенного ContentProvider-a, что поставляется с сервисами Google. Вполне возможно, что Google закроет к нему доступ простым обновлением сервисов. И это даже не обновление самой операционки, а пакета внутри нее, т.е. доступ закроется с обычным обновлением приложений из Play Market.

Читайте также:  Как устанавливается обновление андроид

Но это не самое плохое. Самый большой недостаток в том, что такие фреймворки, как Xposed, позволяют с помощью расширений в пару кликов подменить как ANDROID_ID, так и GSF_ID. Подменить локально сохраненный идентификатор из предыдущего способа сложнее, поскольку это предполагает как минимум базовое изучение работы приложения.

Приложение Device ID Changer в связке с Xposed позволяет подменять практически любой идентификатор. В бесплатной версии — только ANDROID_ID

Создание цифрового отпечатка (fingerprint) устройства

Идея device-fingerprinting не новая, и активно используется в вебе. У самой популярной библиотеки для создания отпечатка — FingerprintJS — 13 тысяч звезд на GitHub. Она позволяет идентифицировать пользователя без использования cookie.

Рассмотрим идею на примере (цифры взяты приблизительные для иллюстрации).

Возьмем ежедневную аудиторию какого-нибудь Android-приложения. Допустим она составляет 4 миллиона. Сколько среди них устройств марки Samsung? Гораздо меньше, примерно 600 тысяч. А сколько среди устройств Samsung таких, что находятся под управлением Android 9? Уже около 150 тысяч. Выделим среди последних такие, что используют сканер отпечатков пальцев? Это множество устройств еще меньше, ведь у многих планшетов нет сканера отпечатков пальцев, а современные модели опираются на распознавание лица. Получим 25000 устройств. Добавляя больше условий и получая больше информации, можно добиться множеств малых размеров. В идеальном случае — с единственным элементом внутри, что и позволит идентифицировать пользователя. Чем больше пользователей можно различить, тем выше энтропия этой информации.

Среди основных источников информации в Android, доступных без пользовательских разрешений, можно выделить аппаратное обеспечение, прошивку, некоторые настройки устройства, установленные приложения и другие.

Обычно всю добытую информацию хешируют, получая цифровой отпечаток. Его и можно использовать в качестве идентификатора.

Из достоинств метода — его независимость от приложения (в отличие от ANDROID_ID), поскольку при одинаковых показаниях с источников отпечатки будут одинаковыми. Отсюда же вытекает первый недостаток — разные устройства с некоторой вероятностью могут иметь одинаковый отпечаток.

Еще одна особенность отпечатка — не все источники информации стабильны. Например, установленные приложения дадут много энтропии. Возьмите устройство друга, и проверьте, одинаков ли у вас набор приложений. Скорее всего — нет, к тому же приложения могут устанавливаться и удаляться почти каждый день.

Таким образом, метод будет работать при правильном соотношении стабильности и уникальности источников энтропии.

Какой метод выбрать

Итак, мы рассмотрели доступные способы идентификации. Какой же выбрать? Как и в большинстве инженерных задач, единственного правильного решения не существует. Все зависит от ваших требований к идентификатору и от требований к безопасности приложения.

Разумный вариант — использовать сторонние решения с открытыми исходниками. В этом случае за изменениями в политике конфиденциальности будет следить сообщество, вовремя поставляя нужные изменения. За столько лет существования проблемы до сих пор нет популярной библиотеки для ее решения, как это есть для веба. Но среди того, что можно найти на android-arsenal, можно выделить две, обе с открытым исходным кодом.

Android-device-identification — библиотека для получения идентификатора. Судя по коду класса, ответственного за идентификацию, используются аппаратные идентификаторы, ANDROID_ID, и цифровой отпечаток полей из класса Build. Увы, проект уже 2 года как не поддерживается, и в настоящий момент скорее неактуален. Но, возможно, у него еще будет развитие.

Fingerprint-android — совсем новая библиотека. Предоставляет 2 метода: getDeviceId и getFingerprint. Первый опирается на GSF_ID и ANDROID_ID, а второй отдает отпечаток, основанный на информации с аппаратного обеспечения, прошивки и некоторых стабильных настроек устройства. Какая точность у метода getFingerprint — пока неясно. Несмотря на это библиотека начинает набирать популярность. Она проста в интеграции, написана на Kotlin, и не несет за собой никаких зависимостей.

В случае, когда импортирование сторонних зависимостей нежелательно, подойдет вариант с использованием ANDROID_ID и GSF_ID. Но стоит следить за изменениями в обновлениях Android, чтобы быть готовым к моменту, когда доступ к ним будет ограничен.

Если у вас есть вопросы или дополнения — делитесь ими в комментариях. А на этом все, спасибо за внимание!

Источник

mvaisakh / Bringup.md

A small Device Tree Bringup Guide

So, you guys might be wondering, how do these «Developers» get your favourite Custom roms, such as LineageOS, Paranoid Android etc., to their own devices. Well I’m here to Guide you on how to do it, specifically on how to bringup or make your own device tree from scratch or adapting.

Читайте также:  Лучшие процессоры для андроида какие

Gist of this Guide: This is for people with genuine interest in Android OS porting/development. After going through this guide, you should be able to do a total device tree bringup on your own.

Prerequisite: Certain requirements are to be met before you start with this amazing journey.

A brain (The most important part)

A computer/server powerful enough to build android roms (Out of the scope of this guide, though you should check out minimum specifications required to build android from AOSP)

Basic text editing.

A way around Android Build system

Familiarity with Linux/MacOS Command Line Interface

Note: I assume that you already know about Linux directories and Android Build System (How Android.mk works, etc.), which to be explained is out of the scope of this guide.

Note 2: This guide applies to devices that were launched with Project Treble enabled (Android Oreo 8.0+), devices launched without it, are not supported on this thread.

Note 3: I’d be specifically talking about a Qualcomm Device (Snapdragon SDM660 based device, launched with Android Oreo 8.1.0) as a reference on this guide. I’m really not experienced with MediaTek or other SoCs device trees , if anyone knows about them, feel free to add a reply to this thread.

Note 4: This guide uses Paranoid Android as the Android Rom Build System. Each and every rom has a different/unique base. This rom here is based on CodeAuroraForum (CAF) Collaborative Project.

For refreshing, android device trees are certain bits of makefile code (also has certain other parts), that allows the Android Build system to recognise the target device specifications to build for, and what all to be built with it.

According to the Google’s conventions, a device is usually placed in a specific location:

There’s a script located in device/common to populate the basic makefiles according to the format I specified above. But, it’s better to do it manually to have a better understanding and learning on how to do it. Understanding Basic Structure of the device tree

When we look at certain device trees, there are certain files and folders we come across, as you can see here

Let’s break these down:

  • Android.mk: This is the most basic makefile definition for any path to be included in the android build system. This makefiles calls for all other makefiles present in the directory and subdirectories of the device tree. The basic use of this specific makefile is to guard the device tree makefile when not building for our target device.
  • BoardConfig.mk: This contains the Board (SoC/Chipset) specific definition, such as the architecture (arm, arm64, x86, etc.), required build flags and kernel build flags. The flags in these aid during building.
  • device.mk: This makefile contains all the build targets and copy specifications (Such as audio configs, feature configs, etc.). If you want a certain package to be built inline with android rom builds, this where you’d want to define it. The vendor tree makefiles are also called from here.
  • README.md: Contains the basic info about the device. It’s always good to have documentation.
  • config.fs: Read more about it on AOSP.
  • extract-files.sh, setup-makefiles.sh & proprietary-files.txt: These files are linked to each other. These are used to extract proprietary blobs from a device and/or from a stock rom dump. Proprietary-files.txt is a list of proprietary (Non-opensource or blobs with proprietary OEM modifications) binaries, which is to be extracted and pushed to vendor tree. Read more about it from LineageOS Wiki.
  • props.mk or any .prop: These contain the specifications needed for build.prop or commonly known as runtime properties.
  • framework-manifest.xml: These are HIDL manifest required by the system framework features and HAL features to work. Read more about them at AOSP.
  • rootdir directory: This contains the major init scripts that are executed during boot time. These are usually found in etc/ dir of /system and /vendor partition.
  • sepolicy directory: This folder contains the specific SELinux policies that are required for the Mandatory Access Control (MAC). Read more about it on AOSP.
  • overlay: This is an important directory. This contains all the framework additions and removals (Since the android framework is largely based on Java, Kotlin and XML, framework configs are controlled from xmls in overlays rather than flags in BoardConfig.mk).
  • aosp_device-name.mk: This is a common makefile found in most AOSP trees. This specific makefile defines device name and manufacturer and build product details. This makefile for my device can be found in Paranoid Android vendor repo (As I mentioned earlier, every rom has their base, which can also mean they have their own way of including device trees)
  • AndroidProducts.mk: This makefile includes the device specific makefiles, i.e., the above mentioned aosp_device codename.mk on lunching (term used to initialise device trees for build). This makefile also defines the lunch target (Android 10+).
Читайте также:  Инженерное меню андроид как попасть

Now that we know what the Android Device tree are made up of, let’s move on ahead with actually getting our device tree up!

You’ll need to figure out the codename of the device by looking at the build number or reading the build.prop or checking out the stock rom dump.

Since I have a qualcomm device, I started digging into CAF OSS board trees, they have certain codenames for their boards (sdm660 is called falcon), you should be able to find them by a google search. If you can’t find your Board OSS tree, there’s a high chance that it uses a major board type for your specific board (eg., msm8937 uses thorium trees, and since then, sdm450 etc., have used thorium as their base tree). You should take a look at the Board trees present here.

Now my tree here is falcon_64 (64 suffix is here because it’s an arm64 device, your board may or may not have it). Open the OSS Board Tree git repository, and use the tag/branch that matches your android version that you want to bring up. note: CAF tags starting with LA.UM.7.x are Android 9.0 pie, LA.UM.8.x are Android 10, and so on.

Now what we need to do is, create the above mentioned files in the device tree. (It’s better to initialise a repository beforehand)

Starting with Android.mk, we’d need to add the guard conditions (using ifeq ) that should be like:

This means that only if the TARGET_DEVICE variable is set to your device, it will start including this device tree, else this tree would be ignored.

My device’s codename here is X01BD

You should also add an inclusion command so that all other makefiles in the sub directory are included, such as:

Basic Android.mk structure is done!

Moving on to BoardConfig.mk, we need to add architecture specifications, this is where the OSS Board Tree comes in handy, as you can just take all the flags from there. So, almost all the BoardConfig flags are written in a specific format, i.e.,

Note: The ‘#’ here is a comment.

Copy most of the flags from the Board OSS tree, for reference use my BoardConfig to check what to copy and what not to copy. Most of the flags should be similar. Note: Kernel flags may or may not be same across different boards. Make sure you get the proper ones. And additional flag that you might want to add is

This is to allow the selinux to be permissive and help us boot avoiding selinux shenanigans. You should also look into other .mk files for specific flags in the Board OSS tree.

Источник

Оцените статью