시스템 사용자의 패키지 제거

이 문서에서는 시스템 사용자에게 필요하지 않은 패키지를 식별하고 제거하여 성능을 향상시키는 방법을 설명합니다.

불필요한 패키지 비활성화

자동차에서 시스템 사용자는 헤드가 없습니다 . 즉, 시스템 사용자는 사람이 사용하거나 직접 액세스할 수 없습니다. 결과적으로 많은 앱과 서비스는 시스템 사용자에서 실행될 필요가 없으며 성능 향상을 위해 비활성화될 수 있습니다. 따라서 시스템 사용자(사용자 0)를 위해 불필요한 앱을 제거하는 옵션이 제공됩니다.

이 페이지에서는 두 가지 유형의 사용자에 대해 설명합니다.

  • 시스템 . 항상 사용자 0
  • 가득한 . 인간(비시스템 사용자)이 사용하도록 의도된 사용자, 사용자 10+

안드로이드 11

Android 11에서는 config_userTypePackageWhitelistMode 구성을 변경합니다. 플래그를 결합할 수 있습니다. 이 경우 5 1 더하기 4 (플래그 14 의 조합)와 같습니다.

깃발 설명
0 허용 목록을 비활성화합니다. 모든 시스템 패키지를 설치하십시오. 로깅이 없습니다.
1 억지로 시키다. 허용 목록에 있는 경우에만 시스템 패키지를 설치하십시오.
2 허용 목록에 없는 패키지를 기록합니다.
4 허용 목록 파일에 언급되지 않은 패키지는 모든 사용자에게 암시적으로 허용 목록에 추가됩니다.
8 시스템 사용자의 경우 4 와 동일합니다.
16 OTA를 무시합니다. OTA 중에는 시스템 패키지를 설치하지 마세요.
다음과 같은 일반적인 시나리오를 고려하십시오.
  • 전체 허용 목록에 대한 기능을 활성화하려면 1 ( 완전히 적용됨 )
  • 불완전한 허용 목록에 대한 기능을 활성화하려면 5
  • SYSTEM 사용자가 로컬 개발을 쉽게 할 수 있도록 기능을 활성화하려면 9 ( 암시적 허용 목록 )
  • 활성화된 적이 없는 것처럼 기능을 비활성화하려면 16
  • 기능을 비활성화하고 이전 효과를 모두 취소하려면 0

장치의 sysconfig 디렉터리(장치의 시스템 이미지를 빌드하는 데 사용되는 makefile(`.mk`)가 포함된 디렉터리와 동일한 디렉터리)에 XML 파일을 설치해야 합니다. XML 파일 이름을 지정할 때 빌드에서 패키지가 정의된 위치를 포함합니다. 예를 들어 preinstalled-packages-product-car-CAR_PRODUCT_NAME.xml .

<!- this package will be installed for both FULL and SYSTEM user -->
    <install-in-user-type package="com.android.bluetooth"->
        <install-in user-type="FULL" /->
        <install-in user-type="SYSTEM" /->
    </install-in-user-type->

<!- this package will only be installed for both FULL user -->
    <install-in-user-type package="com.android.car.calendar"->
        <install-in user-type="FULL" >
    </install-in-user-type->

안드로이드 9 및 안드로이드 10

Android 9 및 Android 10에서 이 기능을 구성하려면 다음 안내를 따르세요.

  1. frameworks/base/core/res/res/values/config.xml 에서 config_systemUserPackagesBlacklistSupported 구성을 오버레이하고 true 로 설정합니다. 이 기능이 활성화되면 기본적으로 시스템 사용자와 전체 사용자 모두에 대해 모든 패키지가 설치되어야 합니다.
  2. 시스템 사용자에 대해 비활성화해야 하는 패키지를 나열하는 config.xml 파일을 만듭니다. 예:
    <config>
        <!-- This package will be uninstalled for the system user -->
        <system-user-blacklisted-app package="com.google.car.calendar" />
    </config>
    
  3. device.mk 에 줄을 추가하여 파일을 장치의 대상 폴더 system/etc/sysconfig/ 에 복사합니다. 예:
    PRODUCT_COPY_FILES += <full path to the config file>:system/etc/sysconfig/<new denylist config file>.xml
    

결과 확인

결과를 확인하려면 다음을 실행하세요.

$ adb shell dumpsys user | grep PACKAGE_SUBSTRING
$ adb shell pm list packages --user USER_ID PACKAGE_SUBSTRING
$ adb shell cmd user report-system-user-package-whitelist-problems

전제

시스템 사용자에 패키지를 설치 AndroidManifest.xml 하는지 결정하려면 앱의 속성과 모든 활동, 서비스, 브로드캐스트 수신기, 그리고 콘텐츠 제공자. 자세한 내용은 앱 매니페스트 개요를 참조하세요.

패키지 워크플로 비활성화

그림 1. 패키지 워크플로 비활성화

레벨 1, 앱 레벨

1. 앱(또는 앱 컴포넌트)이 싱글톤으로 선언되어 있는지 확인하세요.

앱이 싱글톤 인 경우 시스템은 시스템 사용자에서만 앱을 인스턴스화합니다. 해당 앱은 다중 사용자 인식 앱으로 만들어졌을 가능성이 높습니다. 다중 사용자 인식 앱에 대해 자세히 알아보려면 다중 사용자 인식 앱 구축을 참조하세요.

  1. android:singleUser="true" 에 대한 Android 매니페스트를 확인하세요.
  2. true 인 경우 허용 목록입니다. 시스템 사용자에게 필요합니다.
  3. false 인 경우 계속합니다. 제거하기 전에 다른 기준을 확인하세요.

2. 앱에 보호된 저장소 액세스가 필요한지 확인하세요.

많은 시스템 부팅 서비스는 자격 증명 암호화(CE) 저장소 대신 장치 암호화(DE) 저장소를 사용하는 경우가 많습니다. 또한 직접 부팅을 인식하는 시스템 앱도 기기 암호화 저장소에 의존합니다. 직접 부팅 인식 앱에 대해 자세히 알아보려면 시스템 앱에서 직접 부팅 지원을 참조하세요.

  1. 다양한 시스템 부팅 서비스에 필요한 android:defaultToDeviceProtectedStorage="true" 에 대한 Android 매니페스트를 확인하세요.
  2. true 인 경우 허용 목록입니다.
  3. false 인 경우 계속합니다.

레벨 2, 앱 구성요소

활동

활동에 대해 자세히 알아보려면 활동 소개 를 참조하십시오.

ㅏ. 앱에 활동만 포함되어 있는지 확인

활동은 사용자 인터페이스 지향적입니다. 시스템 사용자는 자동차에서 머리가 없기 때문에 어떤 사람도 시스템 사용자와 상호 작용해서는 안 됩니다. 결과적으로 앱에 활동만 포함되어 있는 경우 해당 앱은 시스템 사용자와 관련이 없을 가능성이 높습니다.

우선순위와 특별 권한을 확인하세요.

  1. 그렇다면 시스템 사용자에게 필요할 수 있습니다.
  2. 아니요 인 경우 시스템 사용자를 허용 목록에 추가하지 마세요.

예를 들어 CTS(호환성 테스트 모음)( com.android.cts.priv.ctsshim )에는 활동만 포함되어 있으며 활동은 인텐트 필터를 테스트하도록 정의됩니다. 하지만 권한이 높기 때문에 테스트 목적으로 시스템 사용자용으로 설치해야 합니다.

서비스

서비스에 대해 자세히 알아보려면 서비스 개요를 참조하세요.

비. 서비스가 비공개로 선언되어 다른 앱에서 액세스할 수 없는지 확인하세요.

서비스가 private 으로 선언되면 다른 패키지는 해당 서비스를 사용하지 않습니다. android:exported="false" 찾으세요. 서비스가 비공개로 선언되었거나 다른 앱에서 액세스할 수 없는 경우 다른 앱에 바인딩될 수 없습니다. 따라서 아래의 C 단계와 D 단계는 관련이 없습니다. 결과적으로 이 구성 요소는 시스템 사용자에게 서비스가 필요한지 여부에 대한 추가 힌트를 제공하지 않습니다.

  1. Yes 인 경우 다음 구성요소를 확인하세요.
  2. 아니요 인 경우 이 구성요소를 계속 확인하세요.

씨. 시스템 사용자에 설치된 앱이 이 서비스에 바인딩될 수 있는지 확인하세요.

수준 1에서 허용 목록에 있는 패키지를 확인하고 해당 패키지가 바인딩된 서비스를 식별합니다. 이 서비스의 인텐트 필터와 다른 패키지의 startService 에서 추적합니다.

이 서비스가 시스템 사용자에 설치된 앱에 바인딩된 경우(예: com.android.car.companiondevicesupport 시스템 사용자에서 실행되도록 허용 목록에 추가됨) 서비스를 허용 목록에 추가하세요.

  1. 그렇다면 허용 목록입니다.
  2. 아니요 인 경우 이 구성요소를 계속 확인하세요.

디. 서비스가 다른 앱에 바인딩되어 있고 포그라운드에서 실행되도록 선언되었는지 확인하세요.

startForeground 찾으세요. 이는 사람들이 포그라운드에서 앱과 상호 작용한다는 것을 의미합니다. 대부분의 경우 이 서비스는 시스템 사용자에게 필요하지 않으며 허용 목록에 추가할 필요도 없습니다.

  1. 그렇다면 허용 목록에 추가하지 마세요.
  2. 아니요 인 경우 계속해서 다음 구성요소를 확인하세요.

이자형. 서비스가 시스템 프로세스에서 실행되도록 정의되어 있는지 확인

AndroidManifest에서 android:process="system" 찾으세요.
서비스가 시스템 프로세스에서 실행되도록 의도적으로 정의된 경우 이는 시스템 서비스와 동일한 프로세스에서 명시적으로 실행되며 시스템 사용자에서 실행되도록 허용 목록에 추가되어야 함을 의미합니다. Android의 메모리 할당 설계의 일부로 시스템 서비스는 마지막으로 종료되는 프로세스 중 일부이며, 이는 해당 속성으로 정의된 서비스의 중요성을 의미합니다. Android의 메모리 할당 설계에 대해 자세히 알아보려면 메모리 부족 킬러를 참조하세요.

  1. 그렇다면 허용 목록에 추가하지 마세요.
  2. 아니요 인 경우 계속해서 다른 구성 요소를 확인하세요.

예를 들어 com.android.networkstack.inprocess 패키지는 android:process="system" 태그가 있는 RegularMaintenanceJobService 포함하므로 허용 목록에 추가되어야 합니다.

콘텐츠 제공자

콘텐츠 제공자에 대해 자세히 알아보려면 콘텐츠 제공자를 참조하세요.

에프. 시스템 사용자에 설치된 앱이 이 공급자에 의존하는지 확인하세요.

레벨 1에서 허용 목록에 있는 패키지를 확인하고 해당 패키지가 의존하는 공급자를 확인하세요. 시스템 사용자에서 실행 중인 앱(예: com.android.car.companiondevicesupport 시스템 사용자에서 실행되도록 허용 목록에 포함되어 있음)이 콘텐츠 제공업체에 의존하는 경우 이 콘텐츠 제공업체도 허용 목록에 포함되어 있는지 확인하세요.

  1. 그렇다면 허용 목록입니다.
  2. 아니요 인 경우 허용 목록에 추가하지 마세요.

예를 들어 com.android.car.EXAMPLE 에 싱글톤 공급자( SystemActionsContentProviderManagedProvisioningActionsContentProvider )가 포함된 경우 시스템 사용자에 대해 허용 목록에 추가되어야 합니다. 그런 다음 com.android.car.EXAMPLE WebViewFactoryProvider 에 대한 android.webkit 에 의존하는 경우 com.android.webview android.webkit 로드한다는 점을 고려하여 시스템 사용자에 대해 허용 목록에 추가되어야 합니다.

샘플 패키지 연습

다음 예에서는 패키지의 AndroidManifest.xml 평가하는 방법을 보여줍니다.

<?xml version="1.0" encoding="utf-8"?>
<!-- 1. Search in the entire manifest for singleUser attribute.
No. Move to step 2 -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.android.providers.calendar"
        android:sharedUserId="android.uid.calendar">
    We can ignore the entire permission section
    <uses-permission android:name="android.permission.READ_CALENDAR" />
    ...
    <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
<!-- 2. Look for defaultToDeviceProtectedStorage in application's attribute.
No. Continue evaluating app components. -->
    <application android:label="@string/calendar_storage"
                 android:allowBackup="false"
                 android:icon="@drawable/app_icon"
                 android:usesCleartextTraffic="false">
<!-- a. Contain only activities?
No. Continue to evaluate components other than activities. -->
        <provider android:name="CalendarProvider2" android:authorities="com.android.calendar"
                <!-- b. Is this component exported?
                Yes. Continue evaluating this component.
                f. App on u0 might depend on this? Search for CalendarProvider2 in dumpsys, shows ContentProviderRecord{b710923 u0 com.android.providers.calendar/.CalendarProvider2}
                Yes. Whitelist for system user. -->
                android:label="@string/provider_label"
                android:multiprocess="false"
                android:exported="true"
                android:readPermission="android.permission.READ_CALENDAR"
                android:writePermission="android.permission.WRITE_CALENDAR" />

<activity android:name="CalendarContentProviderTests" android:label="Calendar Content Provider" android:exported="false"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.UNIT_TEST" /> </intent-filter> </activity> <!-- Not service/content provider. Ignore. --> <receiver android:name="CalendarProviderBroadcastReceiver" android:exported="false"> <intent-filter> <action android:name="com.android.providers.calendar.intent.CalendarProvider2"/> <category android:name="com.android.providers.calendar"/> </intent-filter> <intent-filter> <action android:name="android.intent.action.EVENT_REMINDER"/> <data android:scheme="content" /> </intent-filter> </receiver> <service android:name="CalendarProviderIntentService"/> </application> </manifest>