> 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-2.md).

# Interview AOSP 2

### 1. Activity Internals

#### Activity Launch: From `startActivity()` to `onResume()`

**1. Client Request** The call enters `ActivityTaskManagerService` (ATMS) via Binder. In Android 10+, `ActivityManagerService` delegates task/stack management to ATMS.

```java
// frameworks/base/core/java/android/app/Instrumentation.java
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    // Cross-process call into system_server
    int result = ActivityTaskManager.getService()
        .startActivity(whoThread, who.getBasePackageName(), intent, ...);
}
```

**2. ATMS Resolve & Intent Flags** `ActivityStarter` (inside ATMS) resolves the intent via `PackageManagerInternal`, computes the launch mode (`standard`, `singleTop`, `singleTask`, `singleInstance`), and determines if a new task is needed.

```java
// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, ...) {
    // Compute launch flags
    computeLaunchingTaskFlags();
    // Find or create Task
    mTargetTask = mPreferredTaskDisplayArea.getOrCreateRootTask(...);
    // Place activity in task
    mTargetStack.startActivityLocked(mStartActivity, ...);
}
```

**3. Process Start via Zygote** If the target app is not running, ATMS calls `ProcessList.startProcessLocked()`, which builds the `ProcessRecord` and issues a `start()` to Zygote.

```java
// frameworks/base/services/core/java/com/android/server/am/ProcessList.java
boolean startProcessLocked(ProcessRecord app, ...) {
    final String entryPoint = "android.app.ActivityThread";
    return startProcessLocked(hostingRecord, entryPoint, app, uid, ...);
}

private boolean startProcessLocked(...) {
    // Open Zygote socket
    final ZygoteState zygoteState = ZygoteProcess.getZygoteState();
    // Send args: [entryPoint, niceName, uid, gid, ...]
    final Process.ProcessStartResult startResult = ZygoteProcess.start(...);
}
```

**4. ActivityThread Attach** The new process starts `ActivityThread.main()`, creates the main `Looper`, and attaches to ATMS. ATMS replies with `bindApplication()` containing `ApplicationInfo`, providers, and configuration.

```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);
}
```

**5. Application & Activity Creation** ATMS schedules `bindApplication()` back to the app. `ActivityThread` creates the `LoadedApk`, `Instrumentation`, `Application`, and then schedules `Activity.onCreate()` via `H.BIND_APPLICATION` and `H.LAUNCH_ACTIVITY`.

```java
// ActivityThread.java
public final void bindApplication(...) {
    AppBindData data = new AppBindData();
    data.processName = processName;
    data.appInfo = appInfo;
    data.instrumentationName = instrumentationName;
    data.providers = providers;
    sendMessage(H.BIND_APPLICATION, data);
}

private void handleBindApplication(AppBindData data) {
    // Create Instrumentation
    mInstrumentation = new Instrumentation();
    // Create Application
    Application app = data.info.makeApplication(false, mInstrumentation);
    mInitialApplication = app;
    mInstrumentation.callApplicationOnCreate(app);
}

// LAUNCH_ACTIVITY path
public Activity handleLaunchActivity(ActivityClientRecord r, ...) {
    // Creates Window, decorView, WindowManager
    final Activity activity = mInstrumentation.newActivity(...);
    activity.attach(...); // Creates Window, PhoneWindow, WindowManager
    mInstrumentation.callActivityOnCreate(activity, r.state);
    return activity;
}
```

**6. Window & Surface Creation** `Activity.attach()` creates a `PhoneWindow`. `handleResumeActivity()` adds the decor view to `WindowManager`, which triggers `ViewRootImpl.setView()`. `ViewRootImpl` requests a `Surface` from `WindowManagerService` via `relayoutWindow()`, and `WMS` allocates a `SurfaceControl` from `SurfaceFlinger`.

```java
// Activity.java
final void attach(Context context, ActivityThread aThread, ...) {
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    mWindow.setWindowManager(...);
    mWindowManager = mWindow.getWindowManager();
}

// ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
    // IPC to WMS
    res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes, ...);
    // Create native Surface
    mSurface = new Surface();
    // Relayout to get real buffer
    relayoutResult = mWindowSession.relayout(mWindow, mSeq, mWindowAttributes,
            requestedWidth, requestedHeight, viewVisibility, ...);
    mSurface.copyFrom(mSurfaceControl); // Now backed by SurfaceFlinger buffer
}
```

***

### 2. Zygote Internals

#### The Fork Model & USAP (Unspecialized App Process)

**Zygote Startup** `init` starts Zygote via `app_process`. It loads the Android runtime, preloads classes/resources, and enters a `select()` loop on a Unix domain socket (`/dev/socket/zygote`).

```cpp
// frameworks/base/core/jni/AndroidRuntime.cpp
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote) {
    JavaVMInitArgs initArgs;
    initArgs.version = JNI_VERSION_1_4;
    // ...
    JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs);
}

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

**Preloading** `ZygoteInit` preloads \~4000 classes, drawables, and shared libraries. This memory is marked read-only and shared across all children via Copy-on-Write (COW).

```java
// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
static void preload() {
    preloadClasses();      // /system/etc/preloaded-classes
    preloadResources();    // com.android.internal.R.array, drawable
    preloadSharedLibraries(); // android, compiler_rt, jnigraphics
    // ...
    // Explicit GC to clean up preload garbage
    gcAndFinalize();
}
```

**USAP (Unspecialized App Process) — Android 10+** To reduce fork latency, Zygote maintains a pool of pre-forked, idle processes (USAP). When an app launch request arrives, Zygote **specializes** a USAP process instead of forking from the main Zygote.

```java
// ZygoteServer.java
Runnable runSelectLoop(String abiList) {
    while (true) {
        // Check for USAP pool refill
        if (mUsapPoolEnabled) {
            fillUsapPool(abiList); // Pre-fork processes
        }
        
        // Poll on Zygote socket and USAP reporting pipes
        StructPollfd[] pollFds = new StructPollfd[...];
        Os.poll(pollFds, -1);
        
        if (isUsapRequest(pollFds)) {
            return usapPoolServer.processCommand(...);
        } else {
            ZygoteConnection connection = peers.get(i);
            return connection.processCommand(this, multipleForksOK);
        }
    }
}
```

**Fork & Specialization** `Zygote.forkAndSpecialize()` calls native `nativeForkAndSpecialize()`, which uses `fork()`. Post-fork, the child calls `specializeAppProcess()` to drop privileges, set SELinux context, and apply `seccomp-bpf` filters.

```cpp
// frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(...) {
    pid_t pid = fork();
    if (pid == 0) {
        // Child process
        SpecializeCommon(env, uid, gid, gids, runtime_flags, ...);
    }
    return pid;
}

static void SpecializeCommon(JNIEnv* env, ...) {
    // Set UID/GID
    setgid(gid);
    setuid(uid);
    
    // SELinux transition
    SetSELinuxContext(...);
    
    // Enable seccomp
    SetSeccompFilter(...);
    
    // Unmount storage if not needed
    UnmountStorage(...);
}
```

***

### 3. Broadcast Internals

#### Broadcast Resolution, Scheduling, and ANR

**Registration** Receivers are registered either statically in `AndroidManifest.xml` (parsed by PMS at boot) or dynamically via `Context.registerReceiver()`. Dynamic receivers are stored in `AMS.mRegisteredReceivers` keyed by `IIntentReceiver` Binder.

```java
// ActivityManagerService.java
public Intent registerReceiver(IApplicationThread caller, String callerPackage,
        IIntentReceiver receiver, IntentFilter filter, ...) {
    synchronized (this) {
        ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
        if (rl == null) {
            rl = new ReceiverList(callerApp, ...);
            mRegisteredReceivers.put(receiver.asBinder(), rl);
        }
        BroadcastFilter bf = new BroadcastFilter(filter, rl, ...);
        rl.add(bf);
        mReceiverResolver.addFilter(bf);
    }
}
```

**Broadcast Enqueue** `broadcastIntentLocked()` resolves the broadcast to a list of receivers (both manifest and registered). It creates a `BroadcastRecord` and places it in a queue.

* **Ordered**: Enqueued to `mOrderedBroadcasts`. Delivered sequentially.
* **Parallel**: Enqueued to `mParallelBroadcasts`. Delivered concurrently to registered receivers.

```java
// ActivityManagerService.java
final int broadcastIntentLocked(...) {
    // Resolve receivers
    List receivers = ...;
    List registeredReceivers = mReceiverResolver.queryIntent(intent, ...);
    
    // Split into parallel and ordered
    if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
        receivers = collectReceiverComponents(intent, ...);
    }
    
    if (ordered) {
        // Build single BroadcastRecord for all receivers
        BroadcastRecord r = new BroadcastRecord(intent, ...);
        r.receivers = receivers;
        mOrderedBroadcasts.add(r);
        scheduleBroadcastsLocked();
    } else {
        // Queue parallel broadcasts
        for (int i = registeredReceivers.size() - 1; i >= 0; i--) {
            BroadcastRecord r = new BroadcastRecord(intent, ...);
            r.receiver = registeredReceivers.get(i);
            mParallelBroadcasts.add(r);
        }
        scheduleBroadcastsLocked();
    }
}
```

**Delivery & ANR** `processNextBroadcast()` dequeues records. For each receiver, it calls `deliverToRegisteredReceiverLocked()`. If the target process is not running, it starts it. An **ANR** is posted via `mHandler.postDelayed(mBroadcastTimeout, timeout)` (default 10s for foreground, 60s for background). If the receiver does not finish in time, `broadcastTimeoutLocked()` triggers ANR.

```java
// ActivityManagerService.java
final void processNextBroadcast(boolean fromMsg) {
    synchronized (mBroadcastQueues) {
        BroadcastQueue queue = mBroadcastQueues[i];
        BroadcastRecord r = queue.mOrderedBroadcasts.get(0);
        
        // Check if current receiver is done
        if (r.receiverTime > 0) {
            long timeout = r.timeout;
            if (now > r.receiverTime + timeout) {
                broadcastTimeoutLocked(r); // ANR
                return;
            }
        }
        
        // Deliver to next receiver
        Object nextReceiver = r.receivers.get(r.nextReceiver++);
        if (nextReceiver instanceof ResolveInfo) {
            // Manifest receiver: start process if needed
            ProcessRecord app = getProcessRecordLocked(...);
            if (app == null) {
                app = startProcessLocked(...);
                r.curApp = app;
                return; // Will resume broadcast when process attaches
            }
        } else {
            // Registered receiver: direct IPC
            performReceiveLocked(r, (BroadcastFilter) nextReceiver, ...);
        }
    }
}

void broadcastTimeoutLocked(BroadcastRecord r) {
    // Log ANR
    mHandler.post(() -> {
        appNotResponding(r.curApp, "Broadcast of " + r.intent);
    });
}
```

**Background Restrictions (Android 8+)** Implicit broadcasts (without a specific target component) are dropped for manifest-registered receivers unless the app is in the foreground or on a whitelist. Explicit broadcasts and registered receivers are still allowed.

```java
// ActivityManagerService.java
if (r.appInfo.targetSdkVersion >= Build.VERSION_CODES.O
        && (r.intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0
        && !r.intent.getComponent() != null) {
    // Implicit broadcast to manifest receiver is blocked
    return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
}
```

***

### 4. Service Internals

#### `startService()` vs `bindService()`

**startService() Path** The client calls `Context.startService()`. This goes to `ActivityManagerService.startService()`. AMS creates a `ServiceRecord`, places it in `mServicesByName`, and if the service is not running, starts the process. The service is then created via `scheduleCreateService()` and `scheduleStartService()`.

```java
// ActivityManagerService.java
ComponentName startServiceLocked(IApplicationThread caller, Intent service, ...) {
    ServiceLookupResult res = retrieveServiceLocked(service, ...);
    ServiceRecord r = res.record;
    
    // Start service if needed
    if (r.app == null) {
        r.app = startProcessLocked(r.processName, ...);
    }
    
    // Send CREATE_SERVICE message to app thread
    r.app.thread.scheduleCreateService(r, r.serviceInfo, ...);
    // Send START_SERVICE
    r.app.thread.scheduleServiceArgs(r, false, r.intent);
}
```

**bindService() Path** `bindService()` adds a `ConnectionRecord` linking the client `IServiceConnection` to the `ServiceRecord`. If the service is not created, it goes through `scheduleCreateService()`. Then `scheduleBindService()` is sent, which calls `Service.onBind()` in the app. The resulting `IBinder` is returned to the client via `publishService()`.

```java
// ActivityManagerService.java
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
        IServiceConnection connection, int flags, ...) {
    ServiceRecord s = retrieveServiceLocked(service, ...).record;
    
    // Create connection record
    ConnectionRecord c = new ConnectionRecord(b, activity, connection, ...);
    s.addConnection(c);
    
    if ((flags & Context.BIND_AUTO_CREATE) != 0) {
        s.app = startProcessLocked(s.processName, ...);
        s.app.thread.scheduleCreateService(s, ...);
    }
    
    // Request binding
    s.app.thread.scheduleBindService(s, service.getExtras(), ...);
}

// App side: Service publishes binder
private void handleBindService(BindServiceData data) {
    Service s = mServices.get(data.token);
    IBinder binder = s.onBind(data.intent);
    ActivityManager.getService().publishService(data.token, data.intent, binder);
}
```

**Service Lifecycle & Death** `ServiceRecord` tracks `startId` for each `startService()` call. `stopService()` removes the start request. When all starts are removed and no bindings exist, `AMS` schedules `scheduleStopService()`. If the hosting process dies, `AMS` calls `serviceDiedLocked()` and restarts the service if `START_STICKY`.

```java
// ActivityManagerService.java
void serviceDiedLocked(ServiceRecord r, ProcessRecord app) {
    if (r.startRequested && (r.startFlags & Service.START_STICKY) != 0) {
        // Reschedule start
        r.pendingStarts.add(new ServiceRecord.StartItem(...));
        startServiceLocked(null, r.intent, ...);
    }
}
```

***

### 5. Creating a System Service

A system service lives in `system_server` and is accessible to apps via `Context.getSystemService()`.

#### Step 1: Define the AIDL Interface

```aidl
// frameworks/base/core/java/android/app/IMySystemService.aidl
package android.app;

import android.os.Bundle;

interface IMySystemService {
    int doSomething(String arg);
    oneway void doSomethingAsync(String arg);
}
```

Add to `frameworks/base/Android.bp` in `srcs` for the `framework` module.

#### Step 2: Implement the Service

```java
// frameworks/base/services/core/java/com/android/server/MySystemService.java
package com.android.server;

import android.app.IMySystemService;
import android.content.Context;
import android.os.Bundle;
import android.os.RemoteException;

public class MySystemService extends IMySystemService.Stub {
    private final Context mContext;
    private final Object mLock = new Object();

    public MySystemService(Context context) {
        mContext = context;
    }

    @Override
    public int doSomething(String arg) throws RemoteException {
        mContext.enforceCallingPermission(
            "android.permission.MY_PERMISSION", "doSomething");
        synchronized (mLock) {
            return arg.length();
        }
    }

    @Override
    public void doSomethingAsync(String arg) throws RemoteException {
        // Async implementation
    }
}
```

#### Step 3: Register in SystemServer

```java
// frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
    // ...
    t.traceBegin("StartMySystemService");
    ServiceManager.addService(Context.MY_SYSTEM_SERVICE, new MySystemService(mSystemContext));
    t.traceEnd();
}
```

#### Step 4: Add to Context and SystemServiceRegistry

```java
// frameworks/base/core/java/android/content/Context.java
public static final String MY_SYSTEM_SERVICE = "my_system_service";
```

```java
// frameworks/base/core/java/android/app/SystemServiceRegistry.java
static {
    // ...
    registerService(Context.MY_SYSTEM_SERVICE, MySystemManager.class,
            new CachedServiceFetcher<MySystemManager>() {
        @Override
        public MySystemManager createService(ContextImpl ctx) {
            IBinder b = ServiceManager.getService(Context.MY_SYSTEM_SERVICE);
            IMySystemService service = IMySystemService.Stub.asInterface(b);
            return new MySystemManager(ctx, service);
        }});
}
```

#### Step 5: Create the Manager Wrapper

```java
// frameworks/base/core/java/android/app/MySystemManager.java
package android.app;

public class MySystemManager {
    private final IMySystemService mService;

    public MySystemManager(Context context, IMySystemService service) {
        mService = service;
    }

    public int doSomething(String arg) {
        try {
            return mService.doSomething(arg);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
}
```

#### Step 6: SELinux & Permissions

Add the permission in `frameworks/base/core/res/AndroidManifest.xml`:

```xml
<<permission android:name="android.permission.MY_PERMISSION"
    android:protectionLevel="signature|privileged" />
```

Add SELinux rules in `system/sepolicy/private/service.te` and `service_contexts`:

```te
# service.te
type my_system_service, system_api_service, service_manager_type;

# service_contexts
my_system_service    u:object_r:my_system_service:s0
```

***

### 6. Creating a Vendor Service

Vendor services live in the vendor partition, run in vendor processes, and are accessed by framework or other vendor code. They use **hwbinder** (HIDL) or **vndbinder** (stable AIDL).

#### Option A: HIDL HAL (Legacy but still common)

**1. Define HIDL Interface**

```hidl
// hardware/interfaces/mydevice/1.0/IMyDevice.hal
package android.hardware.mydevice@1.0;

interface IMyDevice {
    doSomething(string arg) generates (int32_t result);
};
```

**2. Generate Boilerplate** Run `hidl-gen` to generate `Android.bp`, `IMyDevice.h`, `BpHwMyDevice`, `BnHwMyDevice`.

```bash
hidl-gen -Landroidbp -r android.hardware:hardware/interfaces android.hardware.mydevice@1.0
hidl-gen -Lhash -r android.hardware:hardware/interfaces android.hardware.mydevice@1.0
```

**3. Implement the HAL**

```cpp
// vendor/acme/mydevice/1.0/default/MyDevice.cpp
#include <android/hardware/mydevice/1.0/IMyDevice.h>

using namespace android::hardware::mydevice::V1_0;

class MyDevice : public IMyDevice {
public:
    Return<int32_t> doSomething(const hidl_string& arg) override {
        return arg.size();
    }
};

// Entry point
extern "C" IMyDevice* HIDL_FETCH_IMyDevice(const char* /* name */) {
    return new MyDevice();
}
```

**4. Build & Register**

```json
// vendor/acme/mydevice/1.0/default/Android.bp
cc_library_shared {
    name: "android.hardware.mydevice@1.0-impl",
    relative_install_path: "hw",
    vendor: true,
    srcs: ["MyDevice.cpp"],
    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "android.hardware.mydevice@1.0",
    ],
}
```

Register in `manifest.xml`:

```xml
<<hal format="hidl">
    <name>android.hardware.mydevice</name>
    <transport>hwbinder</transport>
    <version>1.0</version>
    <interface>
        <name>IMyDevice</name>
        <instance>default</instance>
    </interface>
</hal>
```

**5. Access from Framework**

```cpp
#include <android/hardware/mydevice/1.0/IMyDevice.h>

sp<IMyDevice> myDevice = IMyDevice::getService();
if (myDevice != nullptr) {
    auto ret = myDevice->doSomething("hello");
}
```

#### Option B: Stable AIDL HAL (Modern, Android 11+)

**1. Define Stable AIDL**

```aidl
// hardware/interfaces/mydevice/aidl/android/hardware/mydevice/IMyDevice.aidl
package android.hardware.mydevice;

@VintfStability
interface IMyDevice {
    int doSomething(String arg);
}
```

**2. Implement**

```java
// vendor/acme/mydevice/aidl/MyDevice.java
package vendor.acme.mydevice;

import android.hardware.mydevice.IMyDevice;
import android.os.RemoteException;

public class MyDevice extends IMyDevice.Stub {
    @Override
    public int doSomething(String arg) throws RemoteException {
        return arg.length();
    }
}
```

Or in C++:

```cpp
// vendor/acme/mydevice/aidl/MyDevice.cpp
#include <aidl/android/hardware/mydevice/BnMyDevice.h>

using aidl::android::hardware::mydevice::BnMyDevice;

class MyDevice : public BnMyDevice {
    ndk::ScopedAStatus doSomething(const std::string& arg, int32_t* result) override {
        *result = arg.size();
        return ndk::ScopedAStatus::ok();
    }
};
```

**3. Build**

```json
// vendor/acme/mydevice/aidl/Android.bp
cc_library_shared {
    name: "vendor.acme.mydevice-aidl",
    vendor: true,
    srcs: ["MyDevice.cpp"],
    shared_libs: [
        "libbinder_ndk",
        "android.hardware.mydevice-V1-ndk_platform",
    ],
}
```

**4. Register with APEX or vndservicemanager**

For a vendor native service exposed via `vndbinder`:

```cpp
// Main entry
int main() {
    ABinderProcess_setThreadPoolMaxThreadCount(1);
    std::shared_ptr<MyDevice> service = ndk::SharedRefBase::make<MyDevice>();
    
    const std::string instance = std::string() + MyDevice::descriptor + "/default";
    binder_status_t status = AServiceManager_addService(service->asBinder().get(), instance.c_str());
    
    ABinderProcess_joinThreadPool();
    return 1;
}
```

Add to `vendor/etc/vintf/manifest.xml`:

```xml
<<hal format="aidl">
    <name>android.hardware.mydevice</name>
    <version>1</version>
    <interface>
        <name>IMyDevice</name>
        <instance>default</instance>
    </interface>
</hal>
```

#### Option C: Vendor Native Service (vndservicemanager)

For vendor-specific services not defined in VINTF, use `vndservicemanager` directly.

```cpp
// vendor/acme/service/MyVendorService.cpp
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>

using namespace android;

int main(int argc, char** argv) {
    // Use /dev/vndbinder
    sp<IServiceManager> sm = defaultServiceManager();
    sp<MyVendorService> service = new MyVendorService();
    
    // Register with vndservicemanager
    sm->addService(String16("vendor.acme.my_service"), service);
    
    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
    return 0;
}
```

**SELinux for Vendor Services**

```te
# vendor/acme/sepolicy/vendor/service.te
type vendor_acme_service, vendor_service, service_manager_type;

# vendor/acme/sepolicy/vendor/service_contexts
vendor.acme.my_service    u:object_r:vendor_acme_service:s0

# vendor/acme/sepolicy/vendor/my_service.te
type my_service, domain;
type my_service_exec, exec_type, vendor_file_type, file_type;

init_daemon_domain(my_service)

# Allow my_service to register with vndservicemanager
allow my_service vndservicemanager:binder { call transfer };
allow my_service vendor_acme_service:service_manager { add find };
```

**Accessing Vendor Service from Framework**

Framework code must use `ServiceManager.getService("vendor.acme.my_service")` with the proper SELinux context (`system_server` must have `find` permission on `vendor_acme_service`). However, **Treble restrictions** prevent direct framework access to arbitrary vendor services; use a HAL interface or a **passthrough** HIDL interface instead.


---

# 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-2.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.
