> For the complete documentation index, see [llms.txt](https://notes.tejpratapsingh.com/_/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://notes.tejpratapsingh.com/_/android-tips/interview/aosp/interview-aosp-1.md).

# Interview AOSP 1

### Boot

#### 1. Walk through the complete Android boot sequence from power-on to `system_server` startup.

**Answer:**

1. **SoC Boot ROM**: Loads and verifies the bootloader from boot media (eMMC/UFS/SSD).
2. **Bootloader** (e.g., U-Boot/LK): Initializes DRAM, loads `boot.img` (kernel + ramdisk), verifies AVB signatures, and jumps to the kernel.
3. **Kernel**: Decompresses, sets up memory management, mounts rootfs from the ramdisk, executes `/init` as PID 1.
4. **First-Stage Init** (`/system/bin/init`): Lives in the `initramfs`. It mounts system, vendor, product partitions using `fstab`, then execs `/system/bin/init` entering second stage.
5. **Second-Stage Init**: Parses `init.rc` scripts, triggers `early-init` → `init` → `late-init`. It starts core daemons (`ueventd`, `logd`, `servicemanager`).
6. **Zygote**: Started by an `init.rc` service. Preloads common Java classes and resources.
7. **Zygote Forks System Server**: Zygote receives a `start-system-server` argument and forks a dedicated process.
8. **System Server**: Enters `com.android.server.SystemServer.main()`, initializes all Java system services.

```cpp
// system/core/init/init.cpp - Second stage entry
int SecondStageMain(int argc, char** argv) {
    // ...
    InitKernelLogging(argv);
    // Parse init.rc
    ActionManager& am = ActionManager::GetInstance();
    Parser& parser = Parser::GetInstance();
    parser.ParseConfig("/system/etc/init/hw/init.rc");
    // ...
    while (true) {
        // Execute pending commands
        am.ExecuteOneCommand();
    }
}
```

***

#### 2. What is the role of the Boot ROM, and how does it verify the next stage bootloader?

**Answer:** The Boot ROM is mask-programmed into the SoC. It locates the bootloader from a predefined physical offset. Verification uses a Root of Trust public key (often fused in OTP/eFuses) to verify a digital signature over the bootloader image.

```cpp
// Conceptual AVB verification in bootloader
bool verify_bootloader(const uint8_t* image, size_t size) {
    AvbSlotVerifyData* out_data;
    const char* requested_partitions[] = {"boot", NULL};
    
    avb_slot_verify(avb_ops, 
                    requested_partitions,
                    "",  // ab_suffix
                    AVB_SLOT_VERIFY_FLAGS_NONE,
                    AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
                    &out_data);
    // Checks vbmeta signature chain against fused key
}
```

***

#### 3. Explain the differences between U-Boot, Little Kernel (LK), and proprietary bootloaders in AOSP.

**Answer:**

* **U-Boot**: Open-source, highly configurable, common on ARM64 development boards. Supports complex scripting and network boot.
* **Little Kernel (LK)**: Minimalist bootloader from Qualcomm. Fast, small footprint. Used extensively on Qualcomm devices. Supports fastboot protocol natively.
* **Proprietary Bootloaders**: OEM-specific (e.g., Samsung S-Boot). Often closed-source, tightly coupled to SoC security features, and may implement custom download/verification protocols.

AOSP expects the bootloader to implement the fastboot protocol and AVB (Android Verified Boot) interfaces.

***

#### 4. How does `avb_verify` work in the context of Verified Boot 2.0 (AVB)?

**Answer:** AVB 2.0 uses a hashtree for integrity and a signed `vbmeta` structure. The bootloader calls `avb_slot_verify()` which:

1. Reads `vbmeta` partition.
2. Verifies the signature chain against the trusted public key.
3. For each partition listed in descriptors, verifies the digest in the hashtree root against the signed expected value.
4. Sets the `androidboot.verifiedbootstate` kernel cmdline parameter.

```cpp
// libavb/avb_slot_verify.c
AvbSlotVerifyResult avb_slot_verify(AvbOps* ops,
                                    const char* const* requested_partitions,
                                    const char* ab_suffix,
                                    AvbSlotVerifyFlags flags,
                                    AvbHashtreeErrorMode hashtree_error_mode,
                                    AvbSlotVerifyData** out_data) {
    // Load vbmeta partition
    // Verify signature with avb_rsa_verify()
    // Iterate AvbVBMetaImageHeader.descriptors
    // For each hashtree descriptor, verify root digest
}
```

***

#### 5. What is the purpose of the `boot.img` header, and how do the V3 and V4 formats differ from V1/V2?

**Answer:** The `boot.img` header tells the bootloader where the kernel, ramdisk, and DTB are located within the partition.

* **V1/V2**: Contained kernel, ramdisk, second stage, recovery DTBO, and DTB. V2 added `boot.img` signature for AVB.
* **V3** (Android 11+): Simplified. Removed second stage, recovery DTBO. Added `vendor_boot` partition to hold vendor ramdisk and kernel modules. Header size reduced.
* **V4** (Android 12+): Extends V3 to support multiple vendor ramdisk fragments for GKI (Generic Kernel Image) modules.

```cpp
// system/tools/mkbootimg/include/bootimg/bootimg.h
struct boot_img_hdr_v3 {
    uint8_t magic[BOOT_MAGIC_SIZE];
    uint32_t kernel_size;       /* size in bytes */
    uint32_t ramdisk_size;      /* size in bytes */
    uint32_t os_version;        /* OS version and patch level */
    uint32_t header_size;       /* size of boot image header in bytes */
    uint32_t reserved[4];
    uint8_t id[SHA256_DIGEST_SIZE]; /* unique id for boot image */
    uint8_t name[BOOT_NAME_SIZE];   /* asciiz product name */
    uint8_t cmdline[BOOT_ARGS_SIZE]; /* kernel command line */
    uint32_t header_version;
};
```

***

#### 6. Describe the process of loading and verifying the `vendor_boot` partition.

**Answer:** The bootloader loads `vendor_boot` alongside `boot`. The `vendor_boot` image contains:

* Vendor ramdisk (modules, vendor-specific init scripts)
* DTB (Device Tree Blob)
* Kernel command line fragments

The bootloader concatenates the kernel cmdline from `boot` and `vendor_boot`. AVB verification ensures the `vendor_boot` hashtree matches the descriptor in `vbmeta`.

```cpp
// In bootloader flow
void load_vendor_boot() {
    boot_img_hdr_v3 vendor_hdr;
    read_partition("vendor_boot", &vendor_hdr, sizeof(vendor_hdr));
    
    // Verify via AVB
    avb_verify_partition("vendor_boot");
    
    // Load vendor ramdisk and dtb
    load_ramdisk(vendor_hdr.ramdisk_addr, vendor_hdr.ramdisk_size);
    load_dtb(vendor_hdr.dtb_addr, vendor_hdr.dtb_size);
}
```

***

#### 7. How does the bootloader pass the kernel command line and device tree (DTB) to the Linux kernel?

**Answer:** The bootloader passes the command line via a CPU register (e.g., `x0`/`r0` pointing to a structure) or by placing it in the device tree `/chosen/bootargs` node. The DTB is passed via a dedicated register pointing to its physical address.

In `start_kernel()`, the architecture-specific setup code parses these:

* `setup_arch()` extracts the DTB address.
* `early_init_dt_scan()` parses `/chosen/bootargs` into `boot_command_line`.

```c
// arch/arm64/kernel/setup.c
void __init setup_arch(char **cmdline_p) {
    // dtb_early_va is set by bootloader
    early_init_dt_scan(dtb_early_va);
    *cmdline_p = boot_command_line;
}
```

***

#### 8. What is the role of `init` in early userspace, and how does it parse `init.rc` scripts?

**Answer:** `init` is PID 1. It sets up the userspace environment: creates directories, mounts filesystems, starts daemons, and sets permissions. It parses `init.rc` using a lexer/parser built into `system/core/init/`.

The `Parser` class handles three types of statements: **Actions** (on `trigger`), **Commands** (within actions), and **Services** (background processes).

```cpp
// system/core/init/init.cpp
int SecondStageMain(int argc, char** argv) {
    // ...
    Parser& parser = Parser::GetInstance();
    parser.AddSectionParser("service", std::make_unique<ServiceParser>());
    parser.AddSectionParser("on", std::make_unique<ActionParser>());
    parser.AddSectionParser("import", std::make_unique<<ImportParser>());
    
    parser.ParseConfig("/system/etc/init/hw/init.rc");
    // ...
}
```

***

#### 9. Explain the difference between early-init, init, and late-init stages in `init.rc`.

**Answer:**

* **`early-init`**: Runs before any device nodes are created. Used for initial cgroup setup, proc/sys mounts, and setting up the init environment.
* **`init`**: Runs after device coldplug (`ueventd` has processed `/sys`). Used for creating directories, symlinks, and setting permissions.
* **`late-init`**: Runs after all `init` actions. Triggers module loading, property setup, and starting core services like `servicemanager`, `surfaceflinger`, `zygote`.

```rc
# init.rc
on early-init
    mount proc /proc /proc
    mkdir /dev/memcg 0700 root root

on init
    sysclktz 0
    copy /proc/cpuinfo /dev/cpuinfo

on late-init
    trigger early-fs
    trigger fs
    trigger post-fs
    trigger zygote-start
```

***

#### 10. How does `init` handle the transition from the rootfs ramdisk to the system partition?

**Answer:** In first-stage `init` (running from `initramfs`), it mounts the real system partition over `/system` (or as root via `switch_root`), then executes `/system/bin/init` to enter second stage. The `initramfs` is freed from memory.

```cpp
// system/core/init/init_first_stage.cpp
int FirstStageMain(int argc, char** argv) {
    // ...
    // Mount system partition
    if (!DoFirstStageMount()) {
        LOG(FATAL) << "Failed to mount required partitions";
    }
    
    // Exec second stage
    const char* path = "/system/bin/init";
    const char* args[] = {path, "second_stage", nullptr};
    execv(path, const_cast<char**>(args));
}
```

***

#### 11. What is the purpose of the `system/etc/init/` directory and how does it relate to first-stage vs second-stage `init`?

**Answer:** `/system/etc/init/` holds `.rc` files packaged inside the system image. These are parsed by second-stage `init` after the system partition is mounted. First-stage `init` only has access to files inside the `initramfs` (e.g., `/init.rc` there). Second-stage `init` imports all `.rc` files from `/system/etc/init/`, `/vendor/etc/init/`, and `/odm/etc/init/` to start module-specific services.

```cpp
// system/core/init/init.cpp
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
    // ...
    for (const auto& path : {"/system/etc/init", "/vendor/etc/init", "/odm/etc/init"}) {
        parser.ParseConfig(path);
    }
}
```

***

#### 12. How do you debug early boot failures before `logd` and `logcat` are available?

**Answer:**

1. **Kernel printk**: Use `printk` in kernel code; read via serial console or `last_kmsg`.
2. **Init logging**: `init` writes to `/dev/kmsg` directly using `InitKernelLogging()`.
3. **Serial Console**: Enable `console=ttyAMA0` in kernel cmdline for UART output.
4. **Ramdump/JTAG**: For hard crashes.
5. **Bootloader logs**: Most bootloaders have their own log buffer accessible via fastboot `oem get_log`.
6. **Init `.rc` debugging**: Add `exec /system/bin/sh` in `init.rc` to drop to a shell at a specific trigger.

```cpp
// system/core/init/logging.cpp
void InitKernelLogging(char** argv) {
    // Redirect stdout/stderr to /dev/kmsg
    android::base::InitLogging(argv, &android::base::KernelLogger, 
                               &android::base::KernelLogger);
}
```

***

#### 13. Explain how dm-verity is initialized during boot and its impact on I/O performance.

**Answer:** `init` (or the kernel via the `verity` kernel parameter) sets up a `dm-verity` device-mapper target over the block device. The root hash is passed via kernel cmdline (`veritykeyid` or `dm="... verity ..."`). Every read triggers a hash verification up the Merkle tree.

**Performance Impact**: Read amplification. A 4KB read may require reading multiple hash blocks. Using **FEC** (Forward Error Correction) adds overhead but allows correction of small corruptions without panic.

```c
// Kernel dm-verity setup (simplified)
static int verity_ctr(struct dm_target *ti, unsigned int argc, char **argv) {
    // argv contains: <data_dev> <hash_dev> <data_block_size> <hash_block_size>
    // <num_data_blocks> <hash_start_block> <algorithm> <root_digest> <salt>
    v->hash_per_block_bits = ffs(v->hash_per_block) - 1;
    // I/O is intercepted and verified here
    ti->type->map = verity_map;
}
```

***

#### 14. What is the purpose of the `vbmeta` partition, and how are rollback indexes used?

**Answer:** `vbmeta` contains signed metadata (descriptors) for all verified partitions. It includes:

* **Hash descriptors**: For partitions without hashtrees (e.g., `boot`).
* **Hashtree descriptors**: For `system`, `vendor`.
* **Rollback indexes**: Monotonic counters stored in tamper-evident storage (RPMB or fuses). If an OS image has a rollback index lower than the stored value, boot is rejected to prevent downgrade attacks.

```cpp
// libavb/avb_vbmeta_image.h
struct AvbVBMetaImageHeader {
    uint8_t required_libavb_version_major;
    uint8_t required_libavb_version_minor;
    // ...
    uint64_t rollback_index_location;
    uint64_t rollback_index;  // Must be >= stored rollback index
};
```

***

#### 15. How does the boot sequence differ between a normal boot and a recovery boot?

**Answer:**

* **Normal Boot**: Bootloader loads `boot.img` → kernel mounts system partition → `init` starts `zygote` → `system_server`.
* **Recovery Boot**: Bootloader loads `recovery.img` (or `boot` with `androidboot.force_normal_boot=0`). The kernel starts `init` from the recovery ramdisk. Recovery `init.rc` starts `/system/bin/recovery` (or `adbd` for sideload). The rootfs stays as ramdisk; `system` partition is mounted at `/system` only if needed for tools.

```rc
# recovery/init.rc
service recovery /system/bin/recovery
    class core
    seclabel u:r:recovery:s0

service adbd /system/bin/adbd --root_seclabel=u:r:su:s0
    class core
    socket adbd stream 660 system system
```

***

### Build

#### 1. Explain the AOSP build system architecture: how do `Soong`, `Kati`, and `Ninja` interact?

**Answer:**

* **Kati**: Converts `Android.mk` (GNU Make syntax) into `.ninja` files. It is a Make clone written in C++.
* **Soong**: The newer build system that reads `Android.bp` (Blueprint files, JSON-like) and generates `.ninja` files directly. It replaces the need for Make for most modules.
* **Ninja**: The low-level build executor. It takes the generated `.ninja` files and runs the actual compilation/linking commands. Ninja is extremely fast at incremental builds.

Flow: `Android.bp` → Soong → `.ninja` → Ninja compiler commands. Legacy `Android.mk` → Kati → `.ninja` → Ninja.

```json
// Android.bp example
cc_binary {
    name: "my_binary",
    srcs: ["main.cpp"],
    shared_libs: ["libutils"],
}
```

***

#### 2. What is the difference between `Android.bp` and `Android.mk`, and when would you still need the latter?

**Answer:**

* **`Android.bp`**: Declarative, JSON-like, parsed by Soong. No conditionals (no `ifeq`). Supports modules like `cc_binary`, `cc_library`, `java_library`, `android_app`. Preferred for all new code.
* **`Android.mk`**: GNU Make syntax, parsed by Kati. Supports complex conditionals and host-side logic. Still needed for:
  * Complex conditional logic not supported in Blueprint.
  * Some legacy host tools.
  * `BUILD_PREBUILT` patterns that haven't been migrated.

```makefile
# Android.mk (legacy)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_lib
LOCAL_SRC_FILES := my_lib.cpp
include $(BUILD_SHARED_LIBRARY)
```

***

#### 3. How does the `Android.bp` module system handle dependencies between shared libraries and static libraries?

**Answer:** Use `shared_libs` for runtime-linked `.so` files and `static_libs` for `.a` files linked at build time. Soong tracks transitive dependencies. If `libA` statically links `libB`, and `libC` links `libA`, `libC` does not automatically get `libB`'s symbols unless `whole_static_libs` is used or `libA` exports the dependency.

```json
cc_library_shared {
    name: "libA",
    static_libs: ["libB"],
    export_static_lib_headers: ["libB"],  // Expose libB headers to users of libA
}

cc_binary {
    name: "my_app",
    shared_libs: ["libA"],
    // Automatically links against libA.so at runtime
}
```

***

#### 4. Describe the purpose of `AndroidProducts.mk`, `BoardConfig.mk`, and `device.mk` in a device build.

**Answer:**

* **`AndroidProducts.mk`**: Defines the list of product makefiles for a lunch target. It sets `PRODUCT_MAKEFILES` which point to the main product definition file.
* **`BoardConfig.mk`**: Hardware-specific settings. Defines partition sizes, kernel config, bootloader type, Wi-Fi/BT drivers, graphics HAL, and SELinux policy directories. It does NOT define user-facing features.
* **`device.mk`** (or `product.mk`): Defines the product composition. Lists packages to install (`PRODUCT_PACKAGES`), properties (`PRODUCT_PROPERTY_OVERRIDES`), permissions, and overlays.

```makefile
# device/acme/mydevice/AndroidProducts.mk
PRODUCT_MAKEFILES := \
    $(LOCAL_DIR)/mydevice.mk

# device/acme/mydevice/BoardConfig.mk
TARGET_NO_BOOTLOADER := false
TARGET_BOARD_PLATFORM := mysoc
BOARD_KERNEL_CMDLINE := console=ttyMSM0 androidboot.hardware=mydevice

# device/acme/mydevice/device.mk
PRODUCT_PACKAGES += \
    my_hal \
    my_app
PRODUCT_PROPERTY_OVERRIDES += ro.product.name=mydevice
```

***

#### 5. How do you add a new HAL implementation to the build without modifying AOSP core repositories?

**Answer:** Place the HAL implementation in the device or vendor directory. Use `Android.bp` with `cc_library_shared` and set `relative_install_path: "hw"`. The module name must match the HAL interface name (e.g., `mydevice.camera@1.0-impl`). Reference it in `device.mk` via `PRODUCT_PACKAGES`.

```json
// device/acme/mydevice/camera/Android.bp
cc_library_shared {
    name: "mydevice.camera@1.0-impl",
    relative_install_path: "hw",
    vendor: true,
    srcs: ["CameraHAL.cpp"],
    shared_libs: [
        "libhidlbase",
        "libhardware",
        "android.hardware.camera.provider@2.4",
    ],
}
```

```makefile
# device/acme/mydevice/device.mk
PRODUCT_PACKAGES += mydevice.camera@1.0-impl
```

***

#### 6. Explain the difference between `eng`, `user`, `userdebug`, and `user` build variants at the build system level.

**Answer:**

* **`eng`**: Development build. Includes all modules, `adb` enabled by default with root access, debug binaries, no optimization.
* **`userdebug`**: Like `user` but with root access via `adb`, debuggable user space, and some profiling tools. Used for field testing.
* **`user`**: Production build. Optimized, no root access, `adb` disabled or limited, no debug tools, strict SELinux enforcing.
* **`user`** (variant target): The `lunch` target name (e.g., `aosp_arm64-eng`) combines product and variant.

```makefile
# build/core/build_variant.mk
ifeq ($(TARGET_BUILD_VARIANT),user)
  # Enable dexpreopt, disable debug features
  WITH_DEXPREOPT := true
endif
ifeq ($(TARGET_BUILD_VARIANT),eng)
  # Include debug tools
  PRODUCT_PACKAGES += su strace
endif
```

***

#### 7. What is the purpose of `sepolicies` in the build, and how are they compiled into the final image?

**Answer:** SELinux policies define security contexts and access rules for processes and files. During build:

1. `.te` (type enforcement) files are parsed by `checkpolicy` (or `secilc` for CIL).
2. Compiled into `sepolicy` binary.
3. Placed in `rootdir/sepolicy` and loaded by `init` early in second stage via `selinux_setup()`.

```makefile
# device/acme/mydevice/sepolicy/file.te
type my_hal_exec, exec_type, vendor_file_type, file_type;

# device/acme/mydevice/sepolicy/my_hal.te
type my_hal, domain;
init_daemon_domain(my_hal)
```

```cpp
// system/core/init/selinux.cpp
bool SelinuxSetupKernelLogging() { /* ... */ }

void SelinuxInitialize() {
    // Load compiled policy
    LoadPolicy();
    // Set enforcing mode
    security_setenforce(1);
}
```

***

#### 8. How does the build system generate OTA packages, and what is the role of `releasetools.py`?

**Answer:** OTA packages are generated by `build/tools/releasetools/`. The process:

1. `ota_from_target_files` takes `target_files.zip` (produced by the build) as input.
2. Computes binary diffs for partition images using `bsdiff`/`imgdiff`.
3. Generates `update.zip` containing updater scripts and payload.

`releasetools.py` contains the core logic for:

* Creating full vs incremental OTAs.
* Signing the payload.
* Generating A/B OTA metadata.

```bash
# Build OTA
./build/tools/releacestools/ota_from_target_files \
    --block \
    -i previous_target_files.zip \
    target_files.zip \
    ota_update.zip
```

```python
# build/tools/releasetools/ota_from_target_files (simplified)
def GenerateABOta(target_file, output_file):
    payload = Payload()
    payload.AddPartition("boot", target_file.GetPartition("boot"))
    payload.AddPartition("system", target_file.GetPartition("system"))
    payload.Sign()  # Uses signing keys
    payload.Write(output_file)
```

***

#### 9. Describe how to create a custom build target that packages additional prebuilt binaries.

**Answer:** Use `cc_prebuilt_binary` or `android_prebuilt_apk` in `Android.bp`, or `include $(BUILD_PREBUILT)` in `Android.mk`. Place the binary in the device tree and reference it.

```json
// device/acme/mydevice/prebuilts/Android.bp
cc_prebuilt_binary {
    name: "my_prebuilt_tool",
    srcs: ["my_prebuilt_tool"],
    stem: "my_tool",
    vendor: true,
}
```

```makefile
# device/acme/mydevice/device.mk
PRODUCT_COPY_FILES += \
    $(LOCAL_PATH)/prebuilts/config.txt:$(TARGET_COPY_OUT_VENDOR)/etc/config.txt

PRODUCT_PACKAGES += my_prebuilt_tool
```

***

#### 10. What are `apex` modules, and how do they change the traditional system image partitioning?

**Answer:** APEX (Android Pony EXpress) is a package format for lower-level system modules. An APEX is a file system image (ext4/erofs) packaged in a zip file, mounted at runtime via loop device.

Changes to partitioning:

* Traditional: Libraries and services are scattered in `/system`, `/vendor`.
* APEX: Self-contained modules (e.g., `com.android.runtime`, `com.android.tzdata`) can be updated independently via Google Play/System Update.

```json
// apex/Android.bp
apex {
    name: "com.android.myapex",
    manifest: "apex_manifest.json",
    file_contexts: "file_contexts",
    binaries: ["my_service"],
    native_shared_libs: ["my_lib"],
}
```

```json
// apex_manifest.json
{
    "name": "com.android.myapex",
    "version": 1
}
```

***

#### 11. How does the build system handle kernel compilation out-of-tree vs in-tree?

**Answer:**

* **In-tree**: Kernel source is inside AOSP (`device/<vendor>/<board>/kernel`). Build system runs `make` directly via `build/build.sh` or `Android.bp` `kernel_build` module.
* **Out-of-tree**: Kernel is in a separate repository. AOSP build uses a prebuilt kernel image (`TARGET_PREBUILT_KERNEL`) or fetches the kernel repo as a Git project and builds it using a custom build rule.

```makefile
# BoardConfig.mk - Prebuilt kernel
TARGET_PREBUILT_KERNEL := $(LOCAL_PATH)/kernel/Image.gz

# BoardConfig.mk - Build kernel from source
TARGET_KERNEL_CONFIG := my_defconfig
TARGET_KERNEL_SOURCE := kernel/acme/mysoc
```

***

#### 12. Explain the purpose of `PRODUCT_COPY_FILES` vs `PRODUCT_PACKAGES` and their build-time implications.

**Answer:**

* **`PRODUCT_COPY_FILES`**: Copies files verbatim from source to target image. No build processing. Used for configs, firmware, scripts. Syntax: `src:dst`.
* **`PRODUCT_PACKAGES`**: Lists modules to build and install. The build system compiles the module, resolves dependencies, and installs the output. Used for binaries, libraries, APKs.

```makefile
# Copy a config file as-is
PRODUCT_COPY_FILES += \
    $(LOCAL_PATH)/init.mydevice.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/init.mydevice.rc

# Build and install a module
PRODUCT_PACKAGES += \
    my_service \
    libmyhal
```

***

#### 13. How do you implement a build-time flag that conditionally compiles source code across multiple modules?

**Answer:** Use `soong_config_module_type` and `soong_config_string_variable`. Define a config in `Android.bp` at the top level, then use it in modules.

```json
// device/acme/mydevice/Android.bp
soong_config_module_type {
    name: "acme_feature",
    module_type: "cc_library_shared",
    config_namespace: "acme",
    variables: ["feature_enabled"],
    bool_variables: ["feature_enabled"],
    value_variables: [],
    properties: ["cflags", "srcs"],
}

soong_config_string_variable {
    name: "feature_enabled",
    values: ["true", "false"],
}

// Usage in another Android.bp
acme_feature {
    name: "libfeature",
    soong_config_variables: {
        feature_enabled: {
            true: {
                cflags: ["-DFEATURE_ENABLED"],
                srcs: ["feature_enabled.cpp"],
            },
            false: {
                srcs: ["feature_disabled.cpp"],
            },
        },
    },
}
```

***

#### 14. What is the role of `bionic` in the build, and how does it differ from glibc-based builds?

**Answer:** **Bionic** is Android's C library. It is smaller, faster, and BSD-licensed compared to glibc. Key differences:

* No `stdio` file locking (not needed for Android's threading model).
* Custom dynamic linker (`/system/bin/linker64`).
* Built-in TLS (Thread Local Storage) optimized for ARM.
* No full POSIX compliance (e.g., no `pthread_cancel`).

In the build, `bionic/` is built early as the foundation for all native code. `libc.so`, `libm.so`, and `libdl.so` are generated from `bionic/libc/`.

```json
// bionic/libc/Android.bp
cc_library_shared {
    name: "libc",
    srcs: [
        "bionic/libc_init.cpp",
        "bionic/pthread_*.cpp",
        // ...
    ],
    stl: "none",  // Bionic is the STL foundation
}
```

***

#### 15. How would you optimize a clean AOSP build time for a large team using distributed build caches?

**Answer:**

1. **ccache**: Enable `USE_CCACHE=1` with a shared NFS/cache server.
2. **RBE (Remote Build Execution)**: Use Google's Bazel/Soong remote execution to distribute compilation across a cluster.
3. **Ninja Pools**: Limit link jobs (`-j` for compile, smaller `-j` for links) to prevent memory exhaustion.
4. **Prebuilt Modules**: Use prebuilt kernel, prebuilt GSI images where possible.
5. **Build Server**: Use a powerful build server with RAM disk for `OUT_DIR`.
6. **Incremental Builds**: Ensure proper dependency tracking in `Android.bp` to avoid over-building.

```bash
# Enable ccache
export USE_CCACHE=1
export CCACHE_DIR=/nfs/ccache

# Distcc for distributed compilation
export DISTCC_HOSTS="build1/16 build2/16 build3/16"
make -j48 CC="distcc clang"
```

***

### Framework

#### 1. Explain the Zygote startup process and why it uses a prefork model.

**Answer:** Zygote is started by `init` with an `app_process` command. It preloads the Android framework classes and resources into memory, then listens on a Unix domain socket (`/dev/socket/zygote`). When a new app needs to start, AMS sends a request to Zygote, which **forks** a new process.

**Why prefork?**

* **Copy-on-Write (COW)**: The child process shares memory pages with Zygote until they are modified. This saves \~100MB+ of RAM per app and drastically reduces startup time.
* **Preloaded state**: Classes like `android.app.Activity`, `Resources`, and graphics buffers are already initialized.

```cpp
// frameworks/base/core/jni/AndroidRuntime.cpp
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote) {
    // ...
}

// frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[]) {
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    }
}
```

```java
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
    // Preload classes and resources
    preloadClasses();
    preloadResources();
    
    // Fork SystemServer
    Runnable r = forkSystemServer(...);
    if (r != null) { r.run(); return; }
    
    // Run zygote server
    caller = zygoteServer.runSelectLoop(abiList);
}
```

***

#### 2. What happens during `ZygoteInit` before the first application process is forked?

**Answer:**

1. **Register Server Socket**: Opens `/dev/socket/zygote` to listen for fork requests.
2. **Preload**: Loads `preloaded-classes` file (typically \~4000 classes), drawables, colors, and shared libraries.
3. **GC**: Runs an explicit GC to clean up any garbage created during preload, ensuring a clean heap for children.
4. **Fork System Server**: Calls `forkSystemServer()` which `fork()`s and then calls `handleSystemServerProcess()`.
5. **Select Loop**: Enters `runSelectLoop()` to block on `poll()` waiting for connections from `ActivityManagerService`.

```java
// ZygoteInit.java
static void preload() {
    preloadClasses();      // /system/etc/preloaded-classes
    preloadResources();    // com.android.internal.R
    preloadSharedLibraries(); // android, compiler_rt, jnigraphics
    preloadTextResources();
    // Ask the VM where the non-managed heap is
    final VMRuntime runtime = VMRuntime.getRuntime();
    runtime.preloadDexCaches();
}
```

***

#### 3. Describe the Binder IPC mechanism: how does a client obtain a reference to a system service?

**Answer:**

1. **Service Registration**: The system service (e.g., `AlarmManagerService`) publishes itself via `ServiceManager.addService("alarm", this)`.
2. **Service Lookup**: The client calls `ServiceManager.getService("alarm")` which returns a `BinderProxy` (Java) or `BpBinder` (native) handle.
3. **Transaction**: The client calls methods on the proxy. The proxy marshals data into a `Parcel`, sends it via `ioctl(BINDER_WRITE_READ)` to `/dev/binder`.
4. **Kernel**: The binder driver copies the transaction to the target process's thread pool.
5. **Server Thread**: A thread in the server process reads the transaction from the binder driver, unmarshals it, and calls the real implementation.

```java
// Client side
IBinder binder = ServiceManager.getService("alarm");
IAlarmManager alarm = IAlarmManager.Stub.asInterface(binder);
alarm.setTimeZone("UTC"); // Goes through BinderProxy
```

```cpp
// Native client side
sp<IServiceManager> sm = defaultServiceManager();
sp<<IBinder> binder = sm->getService(String16("alarm"));
sp<IAlarmManager> alarm = interface_cast<IAlarmManager>(binder);
```

***

#### 4. What is the difference between `BpBinder` and `BBinder`, and how does the proxy/stub pattern work in native code?

**Answer:**

* **`BBinder`**: The server-side implementation. It inherits from `BBinder` and implements `onTransact()`. It lives in the service process.
* **`BpBinder`**: The client-side proxy handle. It holds an integer handle (e.g., handle 1 for `servicemanager`) and sends transactions to the binder driver.

**Pattern**:

* `interface_cast<<IXXX>(binder)` on the client side creates a `BpXXX` object wrapping the `BpBinder`.
* The server side inherits from `BnXXX` which inherits from `BBinder` and routes `onTransact()` to the implementation.

```cpp
// frameworks/native/libs/binder/include/binder/Binder.h
class BBinder : public IBinder {
public:
    virtual status_t onTransact(uint32_t code, const Parcel& data,
                                Parcel* reply, uint32_t flags = 0);
};

class BpBinder : public IBinder {
public:
    explicit BpBinder(int32_t handle);
    virtual status_t transact(uint32_t code, const Parcel& data,
                              Parcel* reply, uint32_t flags = 0);
};

// IMyService.h
class BnMyService : public BnInterface<IMyService> {
    status_t onTransact(uint32_t code, const Parcel& data, 
                        Parcel* reply, uint32_t flags) override {
        switch(code) {
            case DO_SOMETHING: {
                int arg = data.readInt32();
                reply->writeInt32(doSomething(arg));
                return OK;
            }
        }
    }
};
```

***

#### 5. How does `AIDL` differ from `HIDL` and `AIDL` (stable) in terms of interface stability and versioning?

**Answer:**

* **AIDL (Legacy)**: Used for app-to-framework IPC. Not versioned. Changes to the interface require recompiling both sides. Used in `frameworks/base/`.
* **HIDL (Hardware Interface Definition Language)**: Used for HAL-to-framework IPC. Designed for stable, versioned interfaces. Uses explicit minor versioning (e.g., `@1.0`, `@1.1`). Replaced by stable AIDL.
* **Stable AIDL (AIDL-HAL)**: Introduced to replace HIDL. Uses the same syntax as app AIDL but with stability guarantees (`@VintfStability`). Backward compatible. Preferred for HALs in Android 11+.

```aidl
// Stable AIDL (HAL)
package android.hardware.power;
@VintfStability
interface IPower {
    oneway void setMode(int type, boolean enabled);
}
```

```hidl
// HIDL (legacy)
package android.hardware.power@1.0;
interface IPower {
    setMode(PowerMode type, bool enabled) generates ();
};
```

***

#### 6. Explain the role of `ServiceManager` vs `hwservicemanager` vs `vndservicemanager`.

**Answer:**

* **`ServiceManager`**: The original binder context manager (`/dev/binder`). Registers Java/native framework services (e.g., `activity`, `package`). Accessible to apps and system services with `servicemanager` SELinux context.
* **`hwservicemanager`**: Manages HIDL services (`/dev/hwbinder`). Used for HAL interfaces. Has its own SELinux domain. Services register with `IServiceManager::addService()`.
* **`vndservicemanager`**: A separate instance for vendor-specific native services (`/dev/vndbinder`). Isolates vendor services from framework services for Treble compliance. Started in vendor partition.

```cpp
// frameworks/native/cmds/servicemanager/ServiceManager.cpp
int main(int argc, char** argv) {
    // Determine which binder device to use
    const char* dev = "/dev/binder"; // or /dev/hwbinder, /dev/vndbinder
    sp<<ProcessState> proc = ProcessState::init(dev);
    // ...
}
```

***

#### 7. What is the purpose of the `system_server` process, and how is it started from Zygote?

**Answer:** `system_server` hosts all Java system services (`ActivityManagerService`, `WindowManagerService`, `PackageManagerService`, etc.). It is started by Zygote forking a dedicated process and then calling `SystemServer.main()`.

```java
// ZygoteInit.java
private static Runnable forkSystemServer(String abiList, String socketName, 
                                          ZygoteServer zygoteServer) {
    // ...
    pid = Zygote.forkSystemServer(
            parsedArgs.mUid, parsedArgs.mGid,
            parsedArgs.mGids,
            parsedArgs.mRuntimeFlags,
            null,
            parsedArgs.mPermittedCapabilities,
            parsedArgs.mEffectiveCapabilities);
    
    if (pid == 0) { // In child process
        return handleSystemServerProcess(parsedArgs);
    }
}

// SystemServer.java
public static void main(String[] args) {
    new SystemServer().run();
}

private void run() {
    // Initialize system context
    createSystemContext();
    // Start services
    startBootstrapServices(t);
    startCoreServices(t);
    startOtherServices(t);
    // Loop forever
    Looper.loop();
}
```

***

#### 8. Describe the `ActivityThread` initialization sequence when an application process starts.

**Answer:**

1. Zygote forks the app process.
2. `ActivityThread.main()` is called.
3. Creates the main thread `Looper`.
4. Attaches to the `ActivityManagerService` via `IActivityManager.attachApplication()`.
5. AMS replies with a `bindApplication()` call containing the `ApplicationInfo`, providers, etc.
6. `ActivityThread` creates the `Instrumentation`, `Application` object, and calls `Application.onCreate()`.
7. AMS then sends `scheduleLaunchActivity()` to start the first Activity.

```java
// frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
    Looper.prepareMainLooper();
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq); // false = not system
    Looper.loop();
}

private void attach(boolean system, long startSeq) {
    final IActivityManager mgr = ActivityManager.getService();
    mgr.attachApplication(mAppThread, startSeq);
}
```

***

#### 9. How does the `PackageManagerService` scan and resolve packages during boot?

**Answer:** `PMS` scans directories in `PackageParser` to find APKs:

* `/system/framework` (framework-res.apk)
* `/system/app`, `/system/priv-app`
* `/vendor/app`
* `/data/app` (user apps)

For each APK, it:

1. Parses `AndroidManifest.xml` using `PackageParser`.
2. Extracts permissions, components (activities, services, receivers, providers).
3. Performs signature verification and dexopt.
4. Stores resolved info in internal data structures (`mPackages`, `mActivities`, `mServices`).
5. Updates the package database `/data/system/packages.xml`.

```java
// PackageManagerService.java
void scanDirTracedLI(File scanDir, ...) {
    File[] files = scanDir.listFiles();
    for (File file : files) {
        PackageParser.Package pkg = scanPackageTracedLI(file, ...);
        // Commit package to internal structures
        commitPackageSettings(pkg, ...);
    }
}
```

***

#### 10. Explain the difference between `system` permissions, `signature` permissions, and `normal` permissions in `AndroidManifest.xml`.

**Answer:**

* **`normal`**: Granted automatically at install time. Low risk (e.g., `INTERNET`, `ACCESS_NETWORK_STATE`).
* **`signature`**: Granted only if the requesting app is signed with the same certificate as the app that declared the permission. Used for app pairs or OEM apps.
* **`system` (or `privileged`)**: Granted only to apps in the `system/priv-app` directory or signed with the platform key. Dangerous capabilities (e.g., `WRITE_SECURE_SETTINGS`, `DIAGNOSTIC`).

```xml
<!-- Framework declaring a signature permission -->
<<permission android:name="com.myapp.PRIVATE_API"
            android:protectionLevel="signature|privileged" />

<!-- App requesting it -->
<<uses-permission android:name="com.myapp.PRIVATE_API" />
```

***

#### 11. How does the `WindowManagerService` manage window layers and surface composition?

**Answer:** `WMS` maintains a hierarchy of `WindowState` objects. Each window has a `mLayer` value determined by its type and Z-order policy. `WMS` computes the final layer assignment and communicates with `SurfaceFlinger` via `SurfaceControl`.

* **WindowContainer**: Base class for organizing windows (DisplayContent, Task, ActivityRecord).
* **WindowState**: Represents a single window.
* **SurfaceControl**: Creates and manipulates surfaces in SurfaceFlinger.

`WMS` does not directly composite pixels; it tells `SurfaceFlinger` where each surface is via `setGeometry()` and `setLayer()`.

```java
// WindowManagerService.java
void addWindow(Session session, IWindow client, WindowManager.LayoutParams attrs,
               int viewVisibility, int displayId, ...) {
    WindowState win = new WindowState(this, session, client, token, parentWindow,
                                      appOp[0], seq, attrs, viewVisibility, session.mUid,
                                      session.mCanAddInternalSystemWindow);
    win.attach(); // Creates SurfaceControl
    mWindowMap.put(client.asBinder(), win);
    win.setLayer(attrs.type); // Determines Z-order
}
```

***

#### 12. Describe the input event pipeline from kernel to application: `EventHub`, `InputManagerService`, `InputDispatcher`.

**Answer:**

1. **Kernel**: Input drivers (evdev) generate events and write to `/dev/input/eventX`.
2. **EventHub** (native): Scans input devices via `inotify` and `epoll`. Reads raw `input_event` structs from the kernel.
3. **InputReader** (native): Consumes raw events from EventHub. Converts them into `NotifyArgs` (key, motion). Applies calibration, key remapping.
4. **InputDispatcher** (native): Receives `NotifyArgs` on a dedicated thread. Determines the target window using `WMS` hit-testing. Places events into outbound queues per connection.
5. **App**: `InputDispatcher` sends the event via `InputChannel` (Unix socket pair) to the app's `ViewRootImpl`. The app's main thread `Looper` wakes up and processes the event in `deliverInputEvent()`.

```cpp
// frameworks/native/services/inputflinger/reader/EventHub.cpp
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
    // Uses epoll_wait on input device fds
    // Returns raw input_event data
}

// InputDispatcher.cpp
void InputDispatcher::dispatchOnce() {
    nsecs_t nextWakeupTime = LONG_LONG_MAX;
    { // acquire lock
        if (!mPendingEvent) {
            mPendingEvent = mInboundQueue.dequeue();
        }
        // Find target window from WindowManager
        sp<InputWindowHandle> window = findTouchedWindowAtLocked(...)
        // Post to connection
        enqueueDispatchEntryLocked(connection, event, ...);
    }
}
```

***

#### 13. What is the role of `SurfaceFlinger` in the display pipeline, and how does it interact with HWC?

**Answer:** `SurfaceFlinger` is the system compositor. It collects graphic buffers (Surfaces) from all windows, composites them into a final framebuffer, and presents it to the display.

**HWC (Hardware Composer)**:

* `SurfaceFlinger` attempts to offload composition to HWC by setting up layers.
* HWC decides which layers can be handled by the display controller (overlay planes) vs which need GPU composition.
* `SurfaceFlinger` composites only the remaining layers via OpenGL ES, then passes the final output to HWC for display.

```cpp
// frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
void SurfaceFlinger::onMessageReceived(int32_t what) {
    // ...
    compositionengine::CompositionEngine::PresentationArgs args;
    args.layers = mDrawingState.layers;
    mCompositionEngine->present(args);
    
    // Build HWC display list
    for (auto& layer : mLayers) {
        auto& hwcLayer = layer->getHwcLayer();
        hwcLayer->setBuffer(...);
        hwcLayer->setCompositionType(HWC2::Composition::Device); // or Client
    }
    mHwc->presentAndGetFrameFences(); // Commit to display
}
```

***

#### 14. How does the `PowerManagerService` coordinate with the kernel for suspend/resume and wakelocks?

**Answer:** `PowerManagerService` tracks user activity, display state, and wake locks. It decides when the system should sleep.

* **Wake Locks**: Apps/native code acquire wake locks via `PowerManager`. `PMS` tracks them in `mWakeLocks`.
* **Native Daemon**: `PMS` writes to `/sys/power/wake_lock` and `/sys/power/wake_unlock` via `nativeAcquireWakeLock()` in `com_android_server_power_PowerManagerService.cpp`.
* **Autosuspend**: When no wake locks are held and the screen is off, `PMS` calls `goToSleep()`. The native `autosuspend` loop in the kernel eventually allows the system to enter suspend-to-RAM.

```java
// PowerManagerService.java
void goToSleep(long eventTime, int reason, int flags) {
    // ...
    mDirty |= DIRTY_WAKE_LOCKS;
    updatePowerStateLocked(); // Triggers native update
}

// Native side
static void nativeAcquireWakeLock(JNIEnv *env, jclass clazz, jint flags, jstring tag) {
    acquire_wake_lock(PARTIAL_WAKE_LOCK, tagStr); // Writes to /sys/power/wake_lock
}
```

***

#### 15. Explain the `JobScheduler` framework and how it interacts with Doze mode and App Standby.

**Answer:** `JobScheduler` allows apps to defer background work based on conditions (network, charging, idle). `JobSchedulerService` (in `system_server`) manages a queue of `JobStatus` objects.

* **Doze Mode**: When the device is idle (screen off, stationary), `DeviceIdleController` signals `JobSchedulerService` to defer standard jobs. Only "whitelisted" jobs or those with `setRequiresDeviceIdle(true)` run during maintenance windows.
* **App Standby**: `UsageStatsService` tracks app usage. Unused apps enter buckets (ACTIVE, WORKING\_SET, FREQUENT, RARE, RESTRICTED). `JobScheduler` limits job execution frequency based on the bucket.

```java
// JobSchedulerService.java
void onRunJobNow(JobStatus job) {
    if (mDeviceIdleMode && !job.canRunInDoze()) {
        // Defer to next maintenance window
        return;
    }
    // ... execute
}

// DeviceIdleController.java
void becomeInactive() {
    // Schedule alarms for maintenance windows
    scheduleAlarmToEnterIdleMaintenanceMode();
}
```

***

#### 16. What is the difference between a `ContentProvider` running in its own process vs the caller's process?

**Answer:**

* **Same Process**: If the provider and caller share a UID and process, `ActivityThread` returns a direct `ContentProvider` object reference. No IPC overhead.
* **Different Process**: `ActivityThread` returns a `ContentProviderProxy`. Calls go through `IContentProvider` Binder IPC to the provider process. The provider process is started by `AMS` if not already running.

```java
// ActivityThread.java
private IContentProvider acquireProvider(Context c, String auth, int userId, boolean stable) {
    // Check if provider is local
    final ProviderClientRecord pr = mProviderMap.get(name);
    if (pr != null && pr.mProvider != null) {
        return pr.mProvider; // Same process, direct reference
    }
    
    // Remote provider - AMS starts the process and returns a BinderProxy
    IActivityManager.ContentProviderHolder holder = 
        ActivityManager.getService().getContentProvider(...);
    return holder.provider; // This is a ContentProviderProxy (BpBinder)
}
```

***

#### 17. How does the `ActivityManagerService` handle process lifecycle and out-of-memory killing decisions?

**Answer:** `AMS` maintains a list of running processes in `mLruProcesses` (Least Recently Used). Each process has an `oom_adj` score managed by `ProcessList`.

* **Lifecycle**: `AMS` starts processes via Zygote when components need them. It keeps them alive for caching.
* **OOM Killing**: `AMS` updates `oom_score_adj` in `/proc/<pid>/oom_score_adj`. The Linux OOM killer uses this to select victims. Lower priority processes (background, empty) get higher scores and are killed first.
* **LRU Ordering**: `mLruProcesses` is reordered on activity usage. The last process in the list is the first candidate for killing.

```java
// ActivityManagerService.java
final void updateOomAdjLocked() {
    // ...
    for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
        ProcessRecord app = mLruProcesses.get(i);
        computeOomAdjLocked(app, ...);
        applyOomAdjLocked(app); // Writes to /proc/pid/oom_score_adj
    }
}

// ProcessList.java
static final int CACHED_APP_MAX_ADJ = 999; // Empty processes
static final int SERVICE_ADJ = 500;        // Started services
static final int VISIBLE_APP_ADJ = 100;    // Visible apps
static final int PERSISTENT_PROC_ADJ = -12; // System processes
```

***

#### 18. Describe how `BroadcastReceiver` delivery works, including ordered vs unordered broadcasts and background restrictions.

**Answer:**

* **Unordered**: Sent to all receivers simultaneously. Parallel delivery.
* **Ordered**: Delivered one-by-one based on `priority` in the manifest. Each receiver can `abortBroadcast()` to stop propagation.
* **Background Restrictions** (Android 8+): Implicit broadcasts cannot be received by manifest-declared receivers unless the app is in the foreground or the broadcast is exempted (e.g., `BOOT_COMPLETED`). Explicit broadcasts (targeting a specific package/component) are still allowed.

```java
// ActivityManagerService.java
final int broadcastIntentLocked(...) {
    // Resolve receivers
    List receivers = ...;
    
    if ((receivers != null) && ordered) {
        // Build ordered list by priority
        Collections.sort(receivers, new ResolveInfo.DisplayNameComparator(...));
        // Deliver sequentially
        for (int i = 0; i < receivers.size(); i++) {
            deliverToRegisteredReceiverLocked(...);
        }
    } else {
        // Deliver in parallel
        for (...) {
            deliverToRegisteredReceiverLocked(...);
        }
    }
}
```

***

#### 19. What is the purpose of `Looper`, `Handler`, and `MessageQueue` in the Android threading model?

**Answer:**

* **`Looper`**: Prepares a message loop for a thread. `Looper.prepare()` creates a `MessageQueue` and binds it to the thread. `Looper.loop()` blocks waiting for messages.
* **`MessageQueue`**: A linked list of `Message` objects backed by a native `epoll`/`pipe` mechanism for waking the thread.
* **`Handler`**: Sends and processes `Message`s and `Runnable`s on a specific thread's `MessageQueue`. Used to communicate between threads (e.g., worker thread to UI thread).

```java
// Thread with Looper
class LooperThread extends Thread {
    public Handler mHandler;
    public void run() {
        Looper.prepare(); // Creates MessageQueue
        mHandler = new Handler(Looper.myLooper()) {
            public void handleMessage(Message msg) {
                // Process messages
            }
        };
        Looper.loop(); // Blocks forever
    }
}

// Sending a message
mHandler.sendMessage(mHandler.obtainMessage(MSG_DO_WORK, data));
```

***

#### 20. How does the `Resources` framework handle runtime resource overlay (RRO) and static overlay?

**Answer:**

* **Static Overlay**: Compiled into the framework or device build at build time. `aapt2` merges overlay resources with base resources. Defined in `Android.mk`/`Android.bp` with `LOCAL_PACKAGE_OVERLAYS` or `overlay` property.
* **Runtime Resource Overlay (RRO)**: Installed as separate APKs (in `/vendor/overlay` or `/product/overlay`). `AssetManager` loads them at runtime. `OverlayManagerService` (OMS) manages which overlays are enabled per target package. Uses `idmap` to map resource IDs between base and overlay.

```json
// RRO Android.bp
runtime_resource_overlay {
    name: "MyOverlay",
    theme: "MyTheme",
    sdk_version: "current",
    product_specific: true,
}
```

```java
// OverlayManagerService.java
void setEnabled(String packageName, boolean enable, int userId) {
    // Update settings
    mSettings.setEnabled(packageName, userId, enable);
    // Notify ActivityManager to relaunch affected apps
    mActivityManager.scheduleApplicationInfoChanged(...);
}
```

***

### System Service

#### 1. How do you implement a new system service that is accessible to third-party applications?

**Answer:**

1. Define the AIDL interface in `frameworks/base/`.
2. Implement the service in `frameworks/base/services/core/java/...`.
3. Register it in `SystemServer.java` via `ServiceManager.addService()`.
4. Add a `Context.getSystemService()` wrapper in `ContextImpl.java` and `SystemServiceRegistry.java`.
5. Add the service name to `Context.java` constants.
6. **For third-party access**: The AIDL interface must be in the SDK stub (`frameworks/base/api/`). The service methods must be annotated with `@RequiresPermission` and guarded by `PermissionChecker`.

```java
// IMyService.aidl
package android.app;
interface IMyService {
    int doSomething(String arg);
}

// MyService.java (in services)
public class MyService extends IMyService.Stub {
    public int doSomething(String arg) {
        // Permission check
        mContext.enforceCallingPermission(MY_PERMISSION, "doSomething");
        return arg.length();
    }
}

// SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    ServiceManager.addService(Context.MY_SERVICE, new MyService(mContext));
}

// SystemServiceRegistry.java
registerService(Context.MY_SERVICE, MyManager.class,
        new CachedServiceFetcher<MyManager>() {
    @Override
    public MyManager createService(ContextImpl ctx) {
        return new MyManager(ctx.getOuterContext());
    }});
```

***

#### 2. What is the difference between a Java system service and a native system service in terms of registration?

**Answer:**

* **Java Service**: Lives in `system_server`. Registered via `ServiceManager.addService(name, IBinder)`. Clients get a `BinderProxy` and call through JNI Binder.
* **Native Service**: Lives in its own daemon process (e.g., `surfaceflinger`, `cameraserver`). It calls `defaultServiceManager()->addService()` from C++. Clients use `interface_cast<<IXXX>(sm->getService())`.

```cpp
// Native service registration
int main(int argc, char** argv) {
    sp<IServiceManager> sm = defaultServiceManager();
    sp<MyNativeService> service = new MyNativeService();
    sm->addService(String16("my_native_service"), service);
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}
```

```java
// Java service registration
public class MyService extends SystemService {
    @Override
    public void onStart() {
        publishBinderService("my_java_service", new MyServiceImpl());
    }
}
```

***

#### 3. Explain the `SystemService` base class and the `onStart()`, `onBootPhase()`, and `onUserStarting()` lifecycle methods.

**Answer:** All Java system services in `system_server` should extend `SystemService`.

* **`onStart()`**: Called when `SystemServer` starts this service. Publish the binder service here via `publishBinderService()`.
* **`onBootPhase(int phase)`**: Called at global boot milestones (`PHASE_WAIT_FOR_DEFAULT_DISPLAY`, `PHASE_LOCK_SETTINGS_READY`, `PHASE_SYSTEM_SERVICES_READY`, `PHASE_BOOT_COMPLETED`). Services can perform delayed initialization.
* **`onUserStarting()` / `onUserStopped()`**: Called when a user is starting or stopping. Services should load per-user state here.

```java
// frameworks/base/services/core/java/com/android/server/SystemService.java
public abstract class SystemService {
    public abstract void onStart();
    
    public void onBootPhase(int phase) {}
    
    public void onUserStarting(@NonNull TargetUser user) {}
    public void onUserStopped(@NonNull TargetUser user) {}
}

// Example implementation
public class MySystemService extends SystemService {
    @Override
    public void onStart() {
        publishBinderService(Context.MY_SERVICE, mImpl);
    }
    
    @Override
    public void onBootPhase(int phase) {
        if (phase == PHASE_SYSTEM_SERVICES_READY) {
            // Can now call other services
            mWindowManager = getWindowManager();
        }
    }
}
```

***

#### 4. How do you ensure thread safety in a system service that receives concurrent Binder calls?

**Answer:** Binder calls are dispatched from a thread pool (typically 16 threads). The service implementation must synchronize access to shared state.

1. **Synchronized blocks/methods**: Use `synchronized` on a private lock object.
2. **`Handler` with dedicated looper**: Post all mutations to a single handler thread.
3. **`ConcurrentHashMap` / `AtomicReference`**: For lock-free data structures.
4. **ReadWriteLock**: For read-heavy workloads.

Never perform long-running I/O on the Binder thread directly; use an async handler.

```java
public class MyService extends IMyService.Stub {
    private final Object mLock = new Object();
    private final Map<String, Data> mCache = new HashMap<>();
    
    @Override
    public Data getData(String key) {
        synchronized (mLock) {
            return mCache.get(key);
        }
    }
    
    @Override
    public void setData(String key, Data value) {
        synchronized (mLock) {
            mCache.put(key, value);
        }
        // Notify listeners asynchronously
        mHandler.post(() -> notifyListeners(key, value));
    }
}
```

***

#### 5. Describe the watchdog mechanism (`Watchdog.java`) and how to register a system service with it.

**Answer:** `Watchdog` is a singleton thread in `system_server` that monitors critical threads for deadlocks or hangs. It sends a `MONITOR` message to registered handlers and waits for a response. If no response within 60 seconds, it kills `system_server` to generate a tombstone and trigger a restart.

Registration: The service implements `Watchdog.Monitor` and registers in `onStart()`.

```java
// Watchdog.java
public class Watchdog implements Runnable {
    public interface Monitor {
        void monitor();
    }
    
    public void addMonitor(Monitor m) {
        mMonitors.add(m);
    }
    
    public void run() {
        while (true) {
            // Send MESSAGE_WATCHDOG to monitored threads
            // Wait 60s
            // If no ACK, kill system_server
            Process.killProcess(Process.myPid());
            System.exit(10);
        }
    }
}

// MyService.java
public class MyService extends SystemService implements Watchdog.Monitor {
    @Override
    public void onStart() {
        Watchdog.getInstance().addMonitor(this);
    }
    
    @Override
    public void monitor() {
        synchronized (mLock) {
            // If this thread is deadlocked, we won't return
        }
    }
}
```

***

#### 6. How does `ActivityManagerService` enforce background execution limits introduced in recent Android versions?

**Answer:** Starting Android 8.0 (O), background execution limits restrict implicit broadcasts, background services, and wakeup alarms.

* **Background Services**: `AMS` tracks `ActivityManager.RunningServiceInfo`. If an app is not in the foreground (no visible Activity or foreground service), `AMS` throws `IllegalStateException` on `startService()` after a short grace period.
* **Broadcasts**: Implicit broadcasts are dropped for manifest receivers unless the app is in the foreground.
* **JobScheduler**: Replaces background services for deferrable work.

```java
// ActivityManagerService.java
ComponentName startServiceLocked(...) {
    // Check if app is allowed to start background services
    if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.O && !r.isFgService) {
        if (!appIsInForeground && !appHasForegroundService) {
            throw new IllegalStateException(
                "Not allowed to start service " + service
                + ": app is in background");
        }
    }
    // ...
}
```

***

#### 7. Explain the architecture of `ConnectivityService` and how it manages multiple network agents.

**Answer:** `ConnectivityService` is the central network coordinator. It maintains a list of `NetworkAgentInfo` objects, each representing a network (Wi-Fi, Mobile, Ethernet, VPN).

* **NetworkFactory**: Subsystems (Wi-Fi, Telephony) register factories that score and offer networks.
* **NetworkAgent**: Created by the subsystem when a network connects. Communicates with `ConnectivityService` via Binder.
* **NetworkRequests**: Apps request networks (e.g., `requestNetwork()`). `CS` matches the request to the best-scoring `NetworkAgent`.
* **Default Network**: `CS` selects the highest-scoring network as default and updates the routing table and DNS.

```java
// ConnectivityService.java
private void rematchAllNetworksAndRequests() {
    for (NetworkAgentInfo nai : mNetworkAgentInfos) {
        for (NetworkRequestInfo nri : mNetworkRequests) {
            if (nai.satisfies(nri.request)) {
                if (nai.getCurrentScore() > bestScore) {
                    bestNetwork = nai;
                }
            }
        }
    }
    setDefaultNetwork(bestNetwork); // Updates Netd
}
```

***

#### 8. How does `LocationManagerService` interact with GNSS HAL and fuse location providers?

**Answer:** `LocationManagerService` manages location providers:

* **GnssLocationProvider**: Talks to the `android.hardware.gnss` HAL via HIDL/AIDL. Receives raw NMEA, SV status, and location fixes.
* **FusedLocationProvider**: A composite provider that uses `FusedLocationProvider.java` to blend GPS, network, and sensor data.
* **NetworkLocationProvider**: Uses Wi-Fi/cell tower databases.

`LMS` registers providers and forwards location updates to client apps based on criteria (accuracy, power).

```java
// GnssLocationProvider.java
void handleReportLocation(Location location) {
    // Report to LocationManagerService
    mLocationManager.reportLocation(location, false);
}

// LocationManagerService.java
void reportLocation(Location location, boolean passive) {
    synchronized (mLock) {
        for (Receiver receiver : mReceivers.values()) {
            if (receiver.isAllowed(location)) {
                receiver.callLocationChangedLocked(location);
            }
        }
    }
}
```

***

#### 9. Describe the power management flow from `PowerManagerService` to the kernel power HAL.

**Answer:**

1. **User Activity**: Touch or button wakes `EventHub` → `InputManagerService` → `PowerManagerService.userActivity()`.
2. **Wake Lock Updates**: `PMS` updates internal state and decides if the display should change state (ON → DIM → OFF).
3. **Display Power Controller**: `PMS` sends a message to `DisplayPowerController` to change the display state.
4. **Native Sleep Decision**: When no wake locks are held and idle timeout expires, `PMS` calls `nativeSetAutoSuspend()` which writes to `/sys/power/autosleep`.
5. **Power HAL**: `IPower` HAL (e.g., `power.default.so`) receives hints (`POWER_HINT_INTERACTION`, `POWER_HINT_LOW_POWER`) to adjust CPU governor and scheduler settings.

```java
// PowerManagerService.java
void updatePowerStateLocked() {
    // ...
    if (shouldNapAtBedTimeLocked()) {
        napNoUpdateLocked(SystemClock.uptimeMillis());
    }
    // ...
    if (shouldSleep) {
        nativeSetAutoSuspend(true); // Kernel enters suspend
    }
}

// Native
static void nativeSetAutoSuspend(JNIEnv *env, jclass clazz, jboolean enable) {
    autosuspend_enable(enable); // Writes to /sys/power/autosleep
}
```

***

#### 10. How does `BatteryService` monitor battery state and propagate events to the framework?

**Answer:** `BatteryService` polls the `health` HAL (`android.hardware.health@2.0`) via `HealthServiceWrapper`. It reads `sysfs` nodes (`/sys/class/power_supply/battery/uevent`).

When a change is detected:

1. Reads voltage, temperature, status, level.
2. Computes battery stats (e.g., `BatteryStatsImpl`).
3. Sends a sticky `Intent.ACTION_BATTERY_CHANGED` broadcast.
4. Notifies `PowerManagerService` to adjust low-power behavior.

```java
// BatteryService.java
private void processValuesLocked(boolean force) {
    // Read from Health HAL
    mBatteryProps = mHealthInfo;
    
    // Update stats
    mBatteryStats.setBatteryState(...);
    
    // Broadcast
    Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
    intent.putExtra(BatteryManager.EXTRA_LEVEL, mBatteryProps.batteryLevel);
    intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus);
    mHandler.post(() -> ActivityManager.broadcastStickyIntent(intent, ...));
}
```

***

#### 11. Explain the role of `StorageManagerService` and how it handles adopted storage vs portable storage.

**Answer:** `StorageManagerService` (formerly `MountService`) talks to `vold` (Volume Daemon) via Binder.

* **Adopted Storage** (Internal): An SD card encrypted and formatted as internal storage. Apps and data can be moved to it. Managed as a `VolumeRecord` with `type=PUBLIC` and `adopted=true`.
* **Portable Storage**: Standard FAT32/exFAT SD card. Mounted read-only or read-write for media only. Apps cannot be installed on it.

`vold` handles the actual mounting via `fsck` and `mount()` syscalls.

```java
// StorageManagerService.java
void onVolumeCreatedLocked(VolumeInfo vol) {
    if (vol.type == VolumeInfo.TYPE_PUBLIC) {
        if (vol.disk.isAdoptable()) {
            // Offer adoption to user, or auto-adopt if setting enabled
        } else {
            mountVolume(vol.id); // Portable
        }
    }
}
```

***

#### 12. How does `AudioService` manage audio focus, routing, and policy decisions across HAL implementations?

**Answer:** `AudioService` uses `AudioPolicy` and `MediaFocusControl`.

* **Audio Focus**: Apps request focus (`requestAudioFocus()`). `MediaFocusControl` tracks the stack of focus holders. New requests can cause previous holders to receive `AUDIOFOCUS_LOSS`.
* **Routing**: `AudioService` queries `AudioPolicyManager` (native) which decides the output device (speaker, headset, BT A2DP) based on strategy (MEDIA, VOICE\_CALL, etc.).
* **HAL**: `AudioFlinger` (native) mixes streams and writes to `audio_hw_device_t` HAL.

```java
// MediaFocusControl.java
int requestAudioFocus(AudioFocusRequest afr, int streamType, int durationHint) {
    synchronized (mAudioFocusLock) {
        // Remove previous focus from stack
        if (focusGrantDelayed) {
            mFocusStack.push(focusReceiver);
        } else {
            // Send AUDIOFOCUS_LOSS to current holder
            sendFocusLoss(focusStack.peek(), afr);
            mFocusStack.push(focusReceiver);
        }
    }
}
```

***

#### 13. Describe the `CameraService` architecture and how it handles concurrent camera access from multiple apps.

**Answer:** `CameraService` (native) runs in `cameraserver` process. It manages the `ICameraService` Binder interface.

* **HAL**: Talks to `camera.device` HAL (HIDL/AIDL).
* **Concurrent Access**: Only one app can hold the camera at a time. `CameraService` maintains `CameraClient` objects. When a higher-priority client (foreground app) requests the camera, it evicts the lower-priority client via `disconnect()` with error `CameraEvicted`.
* **Multi-Camera**: For devices with logical multi-camera, `CameraService` manages physical camera IDs and streams.

```cpp
// frameworks/av/services/camera/libcameraservice/CameraService.cpp
status_t CameraService::connect(
        const sp<<ICameraClient>& cameraClient,
        int cameraId,
        const String16& clientPackageName,
        int clientUid,
        sp<<ICamera>& device) {
    
    // Check if camera is in use
    if (mActiveClient != nullptr) {
        if (clientUid != mActiveClient->getClientUid()) {
            // Evict lower priority client
            mActiveClient->notifyError(CAMERA_DISCONNECTED);
            mActiveClient->disconnect();
        }
    }
    // Create new camera client
    client = new CameraClient(this, cameraClient, ...);
    mActiveClient = client;
    device = client;
}
```

***

#### 14. What is the purpose of `SensorService`, and how does it batch sensor events for power efficiency?

**Answer:** `SensorService` (native) runs in `system_server`. It connects to the `sensors` HAL (`android.hardware.sensors`).

* **Batching**: Apps can request `maxReportLatencyUs`. `SensorService` accumulates events in a hardware FIFO (if the HAL supports batching) or software buffer, then delivers them in a batch via `sensors_event_t[]` to reduce CPU wakeups.
* **Wake-up Sensors**: If a wake-up sensor (e.g., significant motion) fires, it wakes the AP to deliver the event.
* **Connection**: Each app registers a `SensorEventConnection`. `SensorService` loops in `threadLoop()` reading from HAL and dispatching to connections.

```cpp
// frameworks/native/services/sensorservice/SensorService.cpp
bool SensorService::threadLoop() {
    sensors_event_t buffer[16];
    ssize_t count = device.poll(buffer, 16); // May return batched events
    
    for (ssize_t i = 0; i < count; i++) {
        sensors_event_t& event = buffer[i];
        // Find connections interested in this sensor
        for (sp<SensorEventConnection> connection : mActiveConnections) {
            if (connection->hasSensor(event.sensor)) {
                connection->sendEvents(&event, 1);
            }
        }
    }
    return true;
}
```

***

#### 15. How does `TelephonyRegistry` dispatch phone state changes to multiple listeners securely?

**Answer:** `TelephonyRegistry` maintains a list of `IPhoneStateListener` Binder proxies. When `Phone` state changes (service state, signal strength, call state), it iterates listeners and applies **per-app permissions**.

* **Permissions**: Some events require `READ_PHONE_STATE` or `READ_PRIVILEGED_PHONE_STATE`. `TelephonyRegistry` checks `checkListenerPermission()` before dispatching.
* **User Filtering**: Listeners are filtered by user ID to prevent cross-user leaks.

```java
// TelephonyRegistry.java
void notifyServiceStateForPhoneId(int phoneId, int subId, ServiceState state) {
    synchronized (mRecords) {
        for (Record r : mRecords) {
            if (r.matchPhoneStateListenerEvent(LISTEN_SERVICE_STATE)) {
                if (checkListenerPermission(r, "notifyServiceState")) {
                    try {
                        r.callback.onServiceStateChanged(new ServiceState(state));
                    } catch (RemoteException e) {
                        remove(r.binder);
                    }
                }
            }
        }
    }
}
```

***

#### 16. Explain the `VibratorService` and `LightsService` abstractions over their respective HALs.

**Answer:**

* **VibratorService**: Java service that calls `IVibrator` HAL (e.g., `vibrator.default`). Supports one-shot, waveform (pattern), and perform effects. It acquires a wakelock during vibration to prevent sleep.
* **LightsService**: Manages backlight, notification LED, button backlight. Talks to `ILight` HAL (`light.default`). Maps `LogicalLight` IDs (`BACKLIGHT`, `BATTERY`, `NOTIFICATIONS`) to HAL `type` and `ordinal`.

```java
// VibratorService.java
public void vibrate(int uid, String opPkg, VibrationEffect effect, ...) {
    synchronized (mLock) {
        // Call HAL
        mNativeWrapper.on(...);
        // Acquire wakelock
        mWakeLock.acquire();
    }
}

// LightsService.java
public void setLight(int light, int brightness, int color) {
    LightState state = new LightState();
    state.color = color;
    mNativeWrapper.setLight(light, state); // Calls light HAL
}
```

***

#### 17. How would you add a custom hardware feature (e.g., a proprietary sensor) and expose it through the framework?

**Answer:**

1. **HAL**: Implement the sensor in the vendor HAL (`sensors.<device>.so`). Add a new sensor type (or use `SENSOR_TYPE_DEVICE_PRIVATE_BASE + offset`).
2. **SELinux**: Add `type mysensor_device` and allow `sensorservice` access.
3. **Framework**: In `SensorService`/`SensorManager`, the new sensor appears automatically via HAL enumeration if properly reported in `getSensorsList()`.
4. **App Access**: Apps can discover it via `sensorManager.getSensorList(Sensor.TYPE_ALL)`. For a custom type, use the private base range.

```cpp
// HAL Implementation
static int poll_sensors(struct sensors_poll_device_t *dev,
                        sensors_event_t* data, int count) {
    // Fill custom sensor event
    data[0].sensor = MY_PROPRIETARY_SENSOR_HANDLE;
    data[0].type = SENSOR_TYPE_DEVICE_PRIVATE_BASE + 0x01;
    data[0].timestamp = getTimestamp();
    data[0].data[0] = readHardwareValue();
    return 1;
}
```

***

#### 18. Describe how `DevicePolicyManagerService` enforces enterprise policies at the system service level.

**Answer:** `DevicePolicyManagerService` (DPMS) stores policies per-user in `/data/system/device_policies.xml`. It acts as a gatekeeper for many system functions.

* **Policy Storage**: `ActiveAdmin` objects hold policy state. `DeviceAdminInfo` parses the metadata from the admin app manifest.
* **Enforcement**: DPMS intercepts calls in other services. For example, `PackageManagerService` checks `isUserRestricted()` before installing unknown sources. `WindowManagerService` checks if screen capture is disabled.
* **Provisioning**: `ACTION_PROVISION_MANAGED_DEVICE` sets the Device Owner (DO) or Profile Owner (PO).

```java
// DevicePolicyManagerService.java
boolean isScreenCaptureAllowed(int userHandle) {
    synchronized (this) {
        ActiveAdmin admin = getActiveAdminUncheckedLocked(
            null, userHandle, false);
        return (admin != null) ? admin.disableScreenCapture : true;
    }
}

// WindowManagerService.java checks this before allowing screenshot
if (!mDevicePolicyManager.isScreenCaptureAllowed(userId)) {
    throw new SecurityException("Screen capture disabled by policy");
}
```

***

#### 19. How does `NetworkManagementService` use `netd` to configure iptables and routing rules?

**Answer:** `NetworkManagementService` (NMS) is the Java frontend. `netd` (native daemon, `/system/bin/netd`) is the backend that executes `iptables`, `ip`, and `ndc` commands.

* **Interface**: NMS calls `INetd` AIDL methods (e.g., `firewallSetUidRule()`, `bandwidthSetInterfaceQuota()`).
* **Netd Execution**: `netd` translates these into `iptables -A` or `tc` (traffic control) commands. It also manages the DNS resolver via `/system/etc/resolv.conf` updates.
* **StrictMode**: `netd` enforces `strict` firewall rules for UID-based network blocking.

```java
// NetworkManagementService.java
public void setFirewallUidRule(int chain, int uid, int rule) {
    try {
        mNetdService.firewallSetUidRule(chain, uid, rule);
    } catch (RemoteException e) {
        throw new RuntimeException(e);
    }
}

// Netd Native (FirewallController.cpp)
int FirewallController::setUidRule(Chain chain, int uid, FirewallRule rule) {
    std::string cmd = "iptables -w -A ";
    cmd += chainName(chain);
    cmd += " -m owner --uid-owner " + std::to_string(uid);
    cmd += (rule == ALLOW) ? " -j RETURN" : " -j DROP";
    return execIptables(cmd);
}
```

***

#### 20. What is the role of `AppOpsService` and how does it provide fine-grained permission auditing beyond runtime permissions?

**Answer:** `AppOpsService` tracks "operations" (e.g., `OP_CAMERA`, `OP_RECORD_AUDIO`, `OP_FINE_LOCATION`) per UID/package. It provides:

* **Mode Tracking**: Each op has a mode (`ALLOW`, `DENY`, `IGNORE`, `FOREGROUND`).
* **Runtime Auditing**: Even if an app has the manifest permission, `AppOpsService` can deny the operation at runtime.
* **Privacy Dashboard**: Feeds data to UI showing which apps used which sensors when.
* **Note Operations**: Services call `noteOperation()` which checks and logs usage.

```java
// AppOpsService.java
int noteOperation(int code, int uid, String packageName) {
    synchronized (this) {
        OpEntry op = getOpLocked(code, uid, packageName, true);
        if (op.mode != AppOpsManager.MODE_ALLOWED) {
            // Log rejection
            return AppOpsManager.MODE_IGNORED;
        }
        // Log success and timestamp
        op.noteTime = System.currentTimeMillis();
        return AppOpsManager.MODE_ALLOWED;
    }
}

// CameraService calls this before opening camera
if (AppOpsManager.noteOp(AppOpsManager.OP_CAMERA, uid, package) 
        != AppOpsManager.MODE_ALLOWED) {
    throw new SecurityException("Camera access denied by AppOps");

```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://notes.tejpratapsingh.com/_/android-tips/interview/aosp/interview-aosp-1.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
