yurii.
back to journal
AOSPAugust 2026 · 3 min read

How we disabled privacy indicators on custom Android image

Introduction

Backstory: At work, we're building a device with kiosk mode that helps protect your home. When we were working on taking camera snapshots during dangerous operations (arm/disarm), we had a requirement to show the camera indicator when taking the snapshot. However, since we're using an Android 13 build, it already included a special feature introduced with Android 12 - privacy indicators (you can read more about it here: link).

There were two problems:

  1. We needed to display our own camera icon, and display it in a completely different location than Android's default.
  2. In some scenarios, we needed to show nothing at all, even if the camera was taking snapshots. This was done for user security.

We decided to do it this way: completely disable the system indicator and display the icon overlaying the app ourselves. Sounds simple. It all started with a simple flag:

adb shell cmd device_config put privacy camera_mic_icons_enabled false default

This flag worked, but the problem was that the command with the flag had to be run by someone, which is completely out of the question, because we wouldn't tell the user: "You need to buy a cable here, and then run another command.". So, another way was needed. A rather simple option, like this boolean config in SystemUI properties, seemed like the answer.

<bool name="config_enablePrivacyDot">true</bool>

We set this flag to false, built the image, installed it on the device, and got "50 percent performance." It turned out that this flag only disables the camera itself, which remains active during extended camera use. However, the camera/microphone icon that appears when launching the camera or AudioRecord doesn't use this flag, and the camera remains visible during use.

The next instance was the PrivacyConfig class, which contained the DEFAULT_MIC_CAMERA property. The name, frankly, is completely meaningless, but it turns out it was supposed to enable/disable the visibility of the camera icon.

frameworks/base/packages/SystemUI/src/com/android/systemui/privacy/PrivacyConfig.kt

We changed the value to false:

private const val DEFAULT_MIC_CAMERA = false

Technically, everything worked now. But there was one problem: this configuration completely disabled the privacy indicator, meaning any other app that used the camera would go undetected. So, we needed to make the "hide system privacy indicator" option apply only to our system app.

A new solution is needed

I started digging deeper and discovered this:

All permissions have different levels of sensitivity, and the system typically sets a sensitivity flag for a specific permission for all apps. Even dangerous permissions can be marked as insensitive, and it turns out you can specify different logic for different packages.

Technically, this meant that we could set a specific insensitive flag for the camera for our app, while the system would automatically mark such permissions as sensitive for other apps. So, if there were a way to tell the system, "Consider this specific permission safe for this app", that would solve our problem. The question remained: how to do it?

After a brief search for answers, it was decided to write a small system application with a system signature that would say exactly what was needed when the system was launched: consider this application safe when it uses the camera. In code it would look like this:

context.getPackageManager().updatePermissionFlags(
    Manifest.permission.CAMERA,
    "your.production.app",
    PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED,
    0,
    Process.myUserHandle()
);

context.getPackageManager().updatePermissionFlags(
    Manifest.permission.RECORD_AUDIO,
    "your.production.app",
    PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED,
    0,
    Process.myUserHandle()
);

Writing system application

Before writing the code let's suggest the architecture and describe how the OS works, and how it decides to display the indicator:

Diagrams of architectural pieces

And here is the sequence diagram of the process:

Sequence of operations

The suggested architecture for the app was the following:

packages/apps/PrivacyExemptionHelper/
├── Android.bp
├── AndroidManifest.xml
└── src/
    └── com/
        └── example/
            └── privacyhelper/
                └── BootReceiver.java

frameworks/base/data/etc/
└── privapp-permissions-example-privacyhelper.xml

device/<vendor>/<device>/
└── device.mk                      ← add PRODUCT_COPY_FILES + PRODUCT_PACKAGES

The next step is to create our main application component - broadcast receiver:

packages/apps/PrivacyExemptionHelper/src/com/example/privacyhelper/BootReceiver.java
package com.example.privacyhelper;

import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Process;
import android.util.Log;

public class BootReceiver extends BroadcastReceiver {

    // The package name of the target application, for which camera icon should NOT
    // be displayed.
    private static final String TARGET_PACKAGE = "your.production.app";

    @Override
    public void onReceive(Context context, Intent intent) {
        PackageManager pm = context.getPackageManager();
        try {
            pm.updatePermissionFlags(
                Manifest.permission.CAMERA, TARGET_PACKAGE,
                PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, 0,
                Process.myUserHandle()
            );
            pm.updatePermissionFlags(
                Manifest.permission.RECORD_AUDIO, TARGET_PACKAGE,
                PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED, 0,
                Process.myUserHandle()
            );
            Log.i("PrivacyExemptionHelper", "Exemption applied for " + TARGET_PACKAGE);
        } catch (Exception e) {
            Log.e("PrivacyExemptionHelper", "Failed to apply exemption", e);
        }
    }
}

After this we can create a AndroidManifext.xml file to configure the application:

packages/apps/PrivacyExemptionHelper/AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.privacyhelper">

    <uses-permission android:name="android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application android:label="PrivacyExemptionHelper">
        <receiver android:name=".BootReceiver" android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.intent.action.PACKAGE_ADDED" />
                <action android:name="android.intent.action.PACKAGE_REPLACED" />
                <data android:scheme="package" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

When two primary pieces are built, we need to say the make engine how to build the app:

packages/apps/PrivacyExemptionHelper/Android.bp
android_app {
    name: "PrivacyExemptionHelper",
    srcs: ["src/**/*.java"],
    manifest: "AndroidManifest.xml",
    platform_apis: true,
    certificate: "platform",
    privileged: true,
}

And also, of course, we need to tell the Android OS, that this application requires some unusual permissions, such as ADJUST_RUNTIME_PERMIOSSION_POLICY

frameworks/base/data/etc/privapp-permissions-example-privacyhelper.xml
<permissions>
    <privapp-permissions package="com.example.privacyhelper">
        <permission name="android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY" />
    </privapp-permissions>
</permissions>

And the final part is we need to tell declare this new system application within the build tree:

PRODUCT_PACKAGES += PrivacyExemptionHelper

PRODUCT_COPY_FILES += \
    frameworks/base/data/etc/privapp-permissions-example-privacyhelper.xml:$(TARGET_COPY_OUT_SYSTEM)/etc/permissions/privapp-permissions-example-privacyhelper.xml

This is it!

Now we need to run the build and make sure it's working for our application only!

Glad you learned something new today!~
Y.S.

RELATED PROJECT

AOSP Platform Customizations
A set of AOSP/SystemUI-level platform tweaks: suppressing system notifications on demand, hiding camera/mic privacy indicators on Android 13, log rotation for the on-device MQTT broker via a custom init.rc process, and kiosk-mode setup.
View case study