这是一项颁发经过加密签名的访问令牌的 Web 服务(请参阅 packages/apps/Car/DebuggingRestrictionController/server 中的参考实现)。参考 Web 服务是一项可部署的 Firebase Cloud Functions 函数(如需了解详情,请参阅 Cloud Functions for Firebase)。
前提条件
在部署参考实现之前,请务必完成以下任务。
准备用于对访问令牌进行签名的证书
Token Issuer 会生成 JSON Web Signature (JWS) 作为访问令牌。为了实现最佳的兼容性,参考 Issuer 仅支持 RS256 算法(采用 SHA256 的 RSA 签名)。为了方便实现密钥轮替,请使用证书链(而不是单个证书)对访问令牌进行签名。典型的证书链应包含一个根 CA 证书、一个中间 CA 证书和一个最终实体证书。
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-08-30。"],[],[],null,["Use the instructions on this page to integrate the AAOS Debugging Restriction Controller\n(DRC).\n\n**Figure 1.** DRC app example.\n\nArchitecture\n\nThe DRC architecture is illustrated in Figure 2. Components outlined in red (token issuer and\nDRC) have accompanying reference implementations that you can customize.\n\n**Figure 2.** DRC architecture.\n\nWhat is the DRC?\n\nThe car head unit includes the DRC app (see the reference implementation in\n`packages/apps/Car/DebuggingRestrictionController`). The reference app includes\nthe logic for receiving an access token from the token issuer, validating the token, and\nthen applying debugging restriction changes as specified in the token. The logic includes\nbasic UX elements on the car-side.\n\nWhat is the token issuer?\n\nThis is a web service that issues cryptographically signed access tokens (see the reference\nimplementation in `packages/apps/Car/DebuggingRestrictionController/server`).\nThe reference web service is a deployable Firebase Cloud function (to learn more, see\n[Cloud Functions for\nFirebase](https://firebase.google.com/docs/functions)).\n\nPrerequisites\n\nBefore you deploy a reference implementation, be sure to complete the following tasks.\n\nPrepare certificates for signing access tokens\n\nThe token issuer generates JSON Web Signatures (JWS) as access tokens. For optimal\ncompatibility, the reference issuer only supports the RS256 algorithm (RSA signatures with SHA256).\nTo facilitate key rotation, use a certificate chain instead of a single certificate to sign\naccess tokens. A typical certificate chain should consist of a root CA certificate, an\nintermediate CA certificate, and an end-entity certificate.\n\nThe end-entity certificate signing the JWS tokens is no different than a standard TLS\ncertificate. You can either purchase a certificate from public CAs such as DigiCert or maintain\nyour own certificate chain using self-signed root CA certificates or Hardware Security Modules.\nThe end-entity certificate should be a X509v3 certificate with a Subject Alternative Name\n(SAN) extension. The SAN extension contains an identifier (for example, hostname) of the token\nissuer. Lastly, RSA certificates should be preferred over EC certificates because the token\nissuer only supports RS256.\n\nGoogle provides a shell script for generating self-signed certificates in\n`packages/apps/Car/DebuggingRestrictionController/server/genkey.sh`.\n\nSet up Firebase\n\nThe reference token issuer uses\n[Firebase Authentication](https://firebase.google.com/docs/auth) and\n[Firebase Cloud Function](https://firebase.google.com/docs/functions).\n\nTo set up your Firebase account:\n\n1. To create a Firebase project, see [Add Firebase to\n your Android project](https://firebase.google.com/docs/android/setup).\n2. To enable some Firebase authenticators, see [Where do I\n start with Firebase Authentication?](https://firebase.google.com/docs/auth/where-to-start).\n3. To add an empty Firebase Cloud function, see [Get\n Started](https://firebase.google.com/docs/functions/get-started).\n4. If not already done, install `Node.js`, NPM, and Firebase tools to compile and deploy the token issuer. **Note:** After you've created a Firebase project, you are prompted to download a config file called `google-services.json`. This file doesn't contain sensitive information and is consumed by both the reference DRC app and the token issuer later.\n\nIntegrate the DRC app\n\nThe reference DRC app is located in\n`packages/apps/Car/DebuggingRestrictionController`. The app can be built\n*bundled* in AOSP with [Soong](/docs/setup/build) or\n*unbundled* with [Gradle](https://gradle.org/).\n\nBundled build\n\nTo build a bundled app:\n\n1. Copy the `applicationId`, `projectId`, and `apiKey` from `google-services.json` into `packages/apps/Car/DebuggingRestrictionController/soong/FirebaseApplication.java`. Doing so enables the DRC app to correctly connect to Firebase.\n2. Update these constants in `packages/apps/Car/DebuggingRestrictionController/soong/BuildConfig.java`:\n - `TOKEN_USES_SELF_SIGNED_CA` indicates if self-signed root CA certificates are used. If enabled, the DRC app trusts only the PEM-encoded root CA certificate specified in `ROOT_CA_CERT`.\n - `TOKEN_ISSUER_API_NAME` is the name of the Firebase Cloud function and should match the Cloud function you created earlier in the Firebase Console.\n - `TOKEN_ISSUER_HOSTNAME` should match the Subject Alternative Name in the end-entity certificate that will sign the access tokens.\n - `DRC_TEST_EMAIL` and `DRC_TEST_PASSWORD` are credentials for an optional test account, which can be pre-provisioned in Firebase if you've enabled Email/Password sign-in. These are used for instrumented tests only.\n\nThe app is now configured to use your Firebase account and your certificates.\nIn Android 9 and higher, you must set up\n[privileged permission allowlisting](/docs/core/permissions/perms-allowlist).\nThe allowlist must contain at least `android.permission.MANAGE_USERS`. For example: \n\n```carbon\n\u003cpermissions\u003e\n \u003cprivapp-permissions package=\"com.android.car.debuggingrestrictioncontroller\"\u003e\n \u003cpermission name=\"android.permission.INTERNET\"/\u003e\n \u003cpermission name=\"android.permission.MANAGE_USERS\"/\u003e\n \u003c/privapp-permissions\u003e\n\u003c/permissions\u003e\n```\n\nUnbundled build\n\nUnbundled DRC builds use Gradle to compile the app.\n\nTo create an unbundled build:\n\n1. Confirm you've installed the Android SDK.\n2. Create a text file named `local.properties` in the app's root directory.\n3. Set the location of Android SDK: \n\n ```text\n sdk.dir=path/to/android/sdk\n ```\n4. To set up Firebase, copy `google-services.json` to `packages/apps/Car/DebuggingRestrictionController/app`. Gradle parses the file and automatically sets up the rest.\n5. Define the environment variables. As with bundled builds, you must specify:\n - `$TOKEN_USES_SELF_SIGNED_CA`: true or false;\n - `$ROOT_CA_CERT`: path to the PEM-encoded root CA certificate;\n - `$TOKEN_ISSUER_API_NAME`: name of the Firebase Cloud function;\n - `$TOKEN_ISSUER_HOST_NAME`: SAN in the certificate;\n - `$DRC_TEST_EMAIL` and `$DRC_TEST_EMAI`L: credentials for a test account, debug builds only.\n6. To build the app with Gradle, run a command like this: \n\n ```bash\n $ ./gradlew build\n ```\n | **Note:** An unbundled DRC app must be signed with the platform certificate because it requires a privileged permission, `MANAGE_USERS`. [privileged permission allowlisting](/docs/core/permissions/perms-allowlist) is still required for the same reason.\n\nIntegrate the token issuer\n\nThe reference token issuer is a Firebase Cloud Function implemented in `Node.js`.\nThe function can only be called by an authenticated user. Before deploying the app, you must set\nup the private key and certificates used to sign the JWS tokens.\n\n1. Populate a JSON file with the following contents: \n\n ```component-pascal\n {\n \"key\": \"---BEGIN PRIVATE KEY---\\nRSA_PRIVATE_KEY\\n-----END PRIVATE KEY-----\\n\",\n \"certificates.0\": \"-----BEGIN CERTIFICATE-----\\nTOKEN_SIGNING_CERT\\n-----END CERTIFICATE-----\\n\",\n \"certificates.1\": \"-----BEGIN CERTIFICATE-----\\nINTERMEDIATE_CA_CERT\\n-----END CERTIFICATE-----\\n\",\n \"certificates.2\": \"-----BEGIN CERTIFICATE-----\\nROOT_CA_CERT\\n-----END CERTIFICATE-----\\n\",\n \"expiration\": \"30m\",\n \"issuer\": \"Debugging Access Token Issuer\",\n \"audience\": \"IHU\"\n }\n ```\n\n Certificates are ordered with the end-entity certificate first and root CA certificate\n at the end. The expiration period is customizable and can be set to a longer duration if an\n issued token takes some time before it can be received and consumed by a DRC app. Token\n revocation is not supported.\n2. Upload the configuration to Firebase: \n\n```bash\n$ firebase functions:config:set api_config=\"$(cat YOUR_CONFIG.json)\"\n```\n3. Deploy the Firebase Cloud function: \n\n```bash\n$ firebase deploy --only functions\n```\n4. To manage and monitor your token issuer, see [Manage\n functions deployment and runtime options](https://firebase.google.com/docs/functions/manage-functions).\n\nSet default restrictions\n\nDefault restrictions can be applied before the first boot. Do this with static resource\noverlays to override the defaults in the Android framework. Restrictions can be respectively\napplied on different types of users. To learn about different types of users, see\n[Multi-User Support](/docs/automotive/users_accounts/multi_user).\n\nThe default restriction for the *headless system user* can be configured with\nthe `config_defaultFirstUserRestrictions` string-array in\n`frameworks/base/core/res/res/values/config.xml`. Setting this restriction\nautomatically disables Android Debug Bridge (ADB) until the restriction is removed, for\nexample: \n\n```scdoc\n\u003cstring-array translatable=\"false\" name=\"config_defaultFirstUserRestrictions\"\u003e\n \u003citem\u003eno_debugging_features\u003c/item\u003e\n\u003c/string-array\u003e\n```\n\nThe default restrictions for *regular users* (for example, drivers and passengers),\nand *guests* can be configured in\n`frameworks/base/core/res/res/xml/config_user_types.xml`. You can overlay these\nstrings to set the default restrictions on each type of user respectively, for example: \n\n```carbon\n\u003cuser-types\u003e\n \u003cfull-type name=\"android.os.usertype.full.SECONDARY\" \u003e\n \u003cdefault-restrictions no_debugging_features=\"true\"/\u003e\n \u003c/full-type\u003e\n \u003cfull-type name=\"android.os.usertype.full.GUEST\" \u003e\n \u003cdefault-restrictions no_debugging_features=\"true\"/\u003e\n \u003c/full-type\u003e\n\u003c/user-types\u003e\n```\n| **Note:** We strongly recommend requiring a factory reset before a debugging restriction can be restored."]]