Interagir avec le Centre de sécurité

Redirection vers le Centre de sécurité

Toutes les applications peuvent ouvrir le centre de sécurité à l'aide du android.content.Intent.ACTION_SAFETY_CENTER action (valeur de chaîne android.intent.action.SAFETY_CENTER).

Pour ouvrir le Centre de sécurité, passez un appel depuis une instance Activity:

Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);

startActivity(openSafetyCenterIntent);

Rediriger vers un problème spécifique

Vous pouvez également rediriger vers une fiche d'avertissement spécifique du Centre de sécurité à l'aide d'extras d'intent spécifiques. Ces extras ne sont pas destinés à être utilisés par des tiers. Ils font donc partie de SafetyCenterManager, qui fait partie de @SystemApi. Uniquement les applications système peuvent accéder à ces extras.

Éléments supplémentaires d'intent qui rediriger une fiche d'avertissement spécifique :

  • EXTRA_SAFETY_SOURCE_ID
    • Valeur de chaîne : android.safetycenter.extra.SAFETY_SOURCE_ID
    • Type de chaîne: spécifie l'ID de la source de sécurité de la fiche d'avertissement
    • Obligatoire pour que la redirection vers le problème fonctionne
  • EXTRA_SAFETY_SOURCE_ISSUE_ID
    • Valeur de chaîne: android.safetycenter.extra.SAFETY_SOURCE_ISSUE_ID
    • Type de chaîne : spécifie l'ID de la fiche d'avertissement
    • Obligatoire pour que la redirection vers le problème fonctionne
  • EXTRA_SAFETY_SOURCE_USER_HANDLE
    • Valeur de chaîne: android.safetycenter.extra.SAFETY_SOURCE_USER_HANDLE
    • Type de UserHandle: spécifie UserHandle pour l'avertissement associé carte
    • Facultatif (par défaut, l'utilisateur actuel)

L'extrait de code ci-dessous peut être utilisé à partir d'une instance Activity pour ouvrir depuis l'écran du Centre de sécurité pour un problème spécifique:

UserHandle theUserHandleThisIssueCameFrom = ;

Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER)
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCE_ID, "TheSafetySourceIdThisIssueCameFrom")
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCE_ISSUE_ID, "TheSafetySourceIssueIdToRedirectTo")
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCE_USER_HANDLE, theUserHandleThisIssueCameFrom);

startActivity(openSafetyCenterIntent);

Rediriger vers une sous-page spécifique (à partir d'Android 14)

Sous Android 14 ou version ultérieure, la page du centre de sécurité est divisée en plusieurs sous-pages qui représentent les différents SafetySourcesGroup (sous Android 13, elles s'affichent sous forme d'entrées réductibles).

Il est possible de rediriger vers une sous-page spécifique à l'aide de cet extra d'intent:

  • EXTRA_SAFETY_SOURCES_GROUP_ID
    • Valeur de chaîne : android.safetycenter.extra.SAFETY_SOURCES_GROUP_ID
    • Type de chaîne : spécifie l'ID de l'SafetySourcesGroup
    • Obligatoire pour que la redirection vers la sous-page fonctionne

L'extrait de code ci-dessous peut être utilisé à partir d'une instance Activity pour ouvrir l'écran du centre de sécurité sur une sous-page spécifique :

Intent openSafetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER)
.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID, "TheSafetySourcesGroupId");

startActivity(openSafetyCenterIntent);

Utiliser les API source du Centre de sécurité

Les API sources du Centre de sécurité sont disponibles à l'aide de SafetyCenterManager (qui est un @SystemApi). Le code de la surface de l'API est disponible dans la recherche de code. Le code d'implémentation des API est disponible dans Recherche de code.

Autorisations

Les API sources du Centre de sécurité ne sont accessibles qu'aux applications système de la liste d'autorisation à l'aide des autorisations listées ci-dessous. Pour plus d'informations, reportez-vous à la section Ajout à la liste d'autorisation des autorisations

  • READ_SAFETY_CENTER_STATUS
    • signature|privileged
    • Utilisé pour l'API SafetyCenterManager#isSafetyCenterEnabled() (et non pour pour les sources du centre de sécurité, elles n'ont besoin Autorisation SEND_SAFETY_CENTER_UPDATE)
    • Utilisé par les applications système qui vérifient si le centre de sécurité est activé
    • Accordée uniquement aux applications système de la liste d'autorisation
  • SEND_SAFETY_CENTER_UPDATE
    • internal|privileged
    • Utilisé pour l'API activée et l'API Safety Sources
    • Utilisé par les sources de sécurité uniquement
    • Accordée uniquement aux applications système de la liste d'autorisation

Ces autorisations sont privilégiées et vous ne pouvez les acquérir qu'en les ajoutant au fichier approprié, par exemple le fichier com.android.settings.xml pour l'application Paramètres et au fichier AndroidManifest.xml de l'application. Pour en savoir plus sur le modèle d'autorisations, consultez protectionLevel.

Obtenir le SafetyCenterManager

SafetyCenterManager est une classe @SystemApi accessible depuis les applications système à partir d'Android 13. Cet appel montre comment obtenir SafetyCenterManager :

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
  // Must be on T or above to interact with Safety Center.
  return;
}
SafetyCenterManager safetyCenterManager = context.getSystemService(SafetyCenterManager.class);
if (safetyCenterManager == null) {
  // Should not be null on T.
  return;
}

Vérifier si le Centre de sécurité est activé

Cet appel vérifie si le centre de sécurité est activé. L'appel nécessite l'autorisation READ_SAFETY_CENTER_STATUS ou SEND_SAFETY_CENTER_UPDATE :

boolean isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabled();
if (isSafetyCenterEnabled) {
  // …
} else {
  // …
}

Fournir des données

Les données sources du centre de sécurité avec l'String sourceId donné sont fournies au centre de sécurité avec l'objet SafetySourceData, qui représente une entrée d'interface utilisateur et une liste de problèmes (fiches d'avertissement). La saisie de l'UI et les fiches d'avertissement peuvent avoir des niveaux de gravité différents spécifiés dans la classe SafetySourceData :

  • SEVERITY_LEVEL_UNSPECIFIED
    • Aucun niveau de gravité spécifié
    • Couleur: gris ou transparent (selon le SafetySourcesGroup des entrée)
    • Utilisé pour les données dynamiques qui se présentent comme une entrée statique dans l'UI ou pour afficher une entrée non spécifiée
    • Ne doit pas être utilisée pour les fiches d'avertissement
  • SEVERITY_LEVEL_INFORMATION
    • Informations de base ou suggestion mineure
    • Couleur: vert
  • SEVERITY_LEVEL_RECOMMENDATION
    • Recommandation à l'utilisateur de prendre des mesures concernant ce problème, car il pourrait les mettre en danger
    • Couleur : Jaune
  • SEVERITY_LEVEL_CRITICAL_WARNING
    • Avertissement critique indiquant que l'utilisateur doit prendre des mesures concernant ce problème, car il présente un risque
    • Couleur: rouge

SafetySourceData

L'objet SafetySourceData est composé d'une entrée d'interface utilisateur, de fiches d'avertissement et et invariantes.

  • Instance SafetySourceStatus facultative (entrée de l'interface utilisateur)
  • Liste des instances SafetySourceIssue (fiches d'avertissement)
  • Bonus Bundle facultatifs (à partir de 14)
  • Invariances :
    • La liste SafetySourceIssue doit être composée de problèmes avec des les identifiants.
    • L'instance SafetySourceIssue ne doit pas être d'une importance supérieure à SafetySourceStatus s'il y en a une (sauf si SafetySourceStatus est SEVERITY_LEVEL_UNSPECIFIED, auquel cas SEVERITY_LEVEL_INFORMATION sont autorisés).
    • Les exigences supplémentaires imposées par la configuration de l'API doivent être respectées, Par exemple, si la source concerne uniquement un problème, elle ne doit pas fournir de Instance SafetySourceStatus.

SafetySourceStatus

  • Titre CharSequence obligatoire
  • Résumé des CharSequence obligatoires
  • Niveau de gravité requis
  • Instance PendingIntent facultative pour rediriger l'utilisateur vers la bonne page (par défaut, intentAction est utilisé à partir de la configuration, le cas échéant)
  • Élément IconAction facultatif (affiché sous la forme d'une icône latérale dans l'entrée) composé des éléments suivants:
    • Type d'icône obligatoire, qui doit être l'un des types suivants :
      • ICON_TYPE_GEAR: s'affiche sous la forme d'une roue dentée à côté de l'entrée de l'interface utilisateur.
      • ICON_TYPE_INFO : affiché sous la forme d'une icône d'information à côté de l'entrée de l'UI
    • Obligatoire PendingIntent pour rediriger l'utilisateur vers une autre page
  • Valeur booléenne enabled facultative qui permet de marquer l'entrée de l'UI comme désactivée, de sorte qu'elle ne soit pas cliquable (valeur par défaut : true)
  • Invariantes: <ph type="x-smartling-placeholder">
      </ph>
    • Les instances PendingIntent doivent ouvrir une instance Activity.
    • Si l'entrée est désactivée, elle doit être désignée comme SEVERITY_LEVEL_UNSPECIFIED.
    • Exigences supplémentaires imposées par la configuration de l'API.

SafetySourceIssue

  • Identifiant String unique obligatoire
  • Titre CharSequence obligatoire
  • Sous-titre CharSequence facultatif
  • Récapitulatif obligatoire pour CharSequence
  • Niveau de gravité requis
  • Catégorie de problème facultative, qui doit être l'une des suivantes :
    • ISSUE_CATEGORY_DEVICE : le problème affecte l'appareil de l'utilisateur.
    • ISSUE_CATEGORY_ACCOUNT: le problème affecte les comptes de l'utilisateur.
    • ISSUE_CATEGORY_GENERAL: le problème affecte la sécurité générale de l'utilisateur. Il s'agit de l'option par défaut.
    • ISSUE_CATEGORY_DATA (à partir d'Android 14) : le problème affecte les données de l'utilisateur.
    • ISSUE_CATEGORY_PASSWORDS (à partir d'Android 14) : le problème affecte les mots de passe de l'utilisateur.
    • ISSUE_CATEGORY_PERSONAL_SAFETY (À partir d'Android 14): Le problème affecte la vie privée de l'utilisateur sécurité.
  • Liste des éléments Action que l'utilisateur peut utiliser pour ce problème, chacun Instance Action composée de:
    • Identifiant String unique obligatoire
    • Libellé CharSequence obligatoire
    • Obligatoire PendingIntent pour rediriger l'utilisateur vers une autre page ou pour traiter l'action directement à partir l'écran du Centre de sécurité
    • Valeur booléenne facultative pour spécifier si ce problème peut être résolu directement depuis l'écran du Centre de sécurité (par défaut : false)
    • Message de réussite CharSequence facultatif, à afficher à l'utilisateur lorsque le problème est résolu directement depuis l'écran du Centre de sécurité
  • PendingIntent facultatif appelé lorsque l'utilisateur ignore le problème (par défaut, rien n'est appelé)
  • Identifiant de type de problème String obligatoire. Il est semblable à l'identifiant du problème, mais n'a pas besoin d'être unique et est utilisé pour la journalisation.
  • String facultatif pour l'ID de déduplication. Cela permet de publier le même SafetySourceIssue à partir de différentes sources et de ne l'afficher qu'une seule fois dans l'UI en supposant qu'il a le même deduplicationGroup (à partir d'Android 14). S'il n'est pas spécifié, le problème n'est jamais dédupliqué
  • CharSequence facultatif pour le titre de l'attribution. Il s'agit d'un texte qui affiche d'où provient la fiche d'avertissement ( 14). S'il n'est pas spécifié, le titre de la SafetySourcesGroup
  • Action facultative sur le problème (à partir d'Android 14) qui doit être l'un des suivants: <ph type="x-smartling-placeholder">
      </ph>
    • ISSUE_ACTIONABILITY_MANUAL : L'utilisateur doit résoudre ce problème manuellement. Il s'agit de l'option par défaut.
    • ISSUE_ACTIONABILITY_TIP : Ce problème n'est qu'un conseil et ne nécessite peut-être aucune entrée utilisateur.
    • ISSUE_ACTIONABILITY_AUTOMATIC : Ce problème a déjà été traité et ne nécessite peut-être aucune intervention de l'utilisateur.
  • Comportement de notification facultatif (système d'exploitation Android 14), qui doit être l'une des valeurs suivantes: <ph type="x-smartling-placeholder">
      </ph>
    • NOTIFICATION_BEHAVIOR_UNSPECIFIED : le Centre de sécurité décide si une notification est nécessaire pour la fiche d'avertissement. Il s'agit de l'option par défaut.
    • NOTIFICATION_BEHAVIOR_NEVER: aucune notification n'est publiée.
    • NOTIFICATION_BEHAVIOR_DELAYED: une notification sera publiée il y a quelque temps après le premier signalement du problème.
    • NOTIFICATION_BEHAVIOR_IMMEDIATELY: une notification est publiée dès que le problème est signalé.
  • Notification facultatif, pour afficher une notification personnalisée avec la fiche d'avertissement (à partir d'Android 14). Si aucune valeur n'est spécifiée, Notification est dérivé de la fiche d'avertissement. Composé de :
    • Titre CharSequence obligatoire
    • Récapitulatif obligatoire pour CharSequence
    • Liste des éléments Action que l'utilisateur peut utiliser pour cette notification
  • Invariances :
    • La liste des instances Action doit être composée d'actions ayant des attributs identifiants
    • La liste des instances Action doit contenir un ou deux éléments Action. Si l'exploitabilité n'est pas ISSUE_ACTIONABILITY_MANUAL, avoir une valeur Action nulle est autorisée.
    • L'élément OnDismiss PendingIntent ne doit pas ouvrir une instance Activity
    • Exigences supplémentaires imposées par la configuration de l'API

Des données sont fournies au Centre de sécurité lors de certains événements. Il est donc nécessaire de spécifier ce qui a poussé la source à fournir à SafetySourceData une instance SafetyEvent.

SafetyEvent

  • Type obligatoire, qui doit être l'un des suivants :
    • SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED : l'état de la source a changé.
    • SAFETY_EVENT_TYPE_REFRESH_REQUESTED: réponse à une actualisation/une nouvelle analyse le signal du Centre de sécurité ; utilisez ceci à la place de SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED pour que le Centre de sécurité puisse suivre la demande d'actualisation/nouvelle analyse.
    • SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED : nous avons résolu SafetySourceIssue.Action directement depuis l'écran du Centre de sécurité. Utilisez-le à la place de SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED pour que le Centre de sécurité puisse suivre la résolution de SafetySourceIssue.Action.
    • SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED: nous avons tenté de résoudre le problème SafetySourceIssue.Action directement sur l'écran du Centre de sécurité, mais n’a pas réussi à le faire ; utilisez ceci à la place de SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED pour que le Centre de sécurité puisse échec du canal SafetySourceIssue.Action.
    • SAFETY_EVENT_TYPE_DEVICE_LOCALE_CHANGED: langue de l'appareil a changé, nous modifions donc le texte des données fournies. il fait autorisé à utiliser SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED pour cela.
    • SAFETY_EVENT_TYPE_DEVICE_REBOOTED: nous fournissons ces données dans le cadre d'un démarrage initial, car les données du centre de sécurité ne sont pas conservées les redémarrages il est autorisé d'utiliser SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED pour cela.
  • Identifiant String facultatif pour l'ID de diffusion d'actualisation.
  • Identifiant String facultatif pour l'instance SafetySourceIssue en cours de résolution.
  • Identifiant String facultatif pour l'instance SafetySourceIssue.Action en cours de résolution.
  • Invariances :
    • L'ID de diffusion d'actualisation doit être fourni si le type est SAFETY_EVENT_TYPE_REFRESH_REQUESTED
    • Les ID de problème et d'action doivent être fournis si le type est SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED ou SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED.

Vous trouverez ci-dessous un exemple de la façon dont une source peut fournir des données au Centre de sécurité (dans ce cas, il s'agit d'une entrée avec une seule fiche d'avertissement) :

PendingIntent redirectToMyScreen =
    PendingIntent.getActivity(
        context, requestCode, redirectToMyScreenIntent, PendingIntent.FLAG_IMMUTABLE);
SafetySourceData safetySourceData =
    new SafetySourceData.Builder()
        .setStatus(
            new SafetySourceStatus.Builder(
                    "title", "summary", SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION)
                .setPendingIntent(redirectToMyScreen)
                .build())
        .addIssue(
            new SafetySourceIssue.Builder(
                    "MyIssueId",
                    "title",
                    "summary",
                    SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION,
                    "MyIssueTypeId")
                .setSubtitle("subtitle")
                .setIssueCategory(SafetySourceIssue.ISSUE_CATEGORY_DEVICE)
                .addAction(
                    new SafetySourceIssue.Action.Builder(
                            "MyIssueActionId", "label", redirectToMyScreen)
                        .build())
                .build())
        .build();
SafetyEvent safetyEvent = new SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build();
safetyCenterManager.setSafetySourceData("MySourceId", safetySourceData, safetyEvent);

Obtenir les dernières données fournies

Vous pouvez obtenir les dernières données fournies à Safety Center pour une source appartenant à votre application. Vous pouvez les utiliser pour afficher quelque chose dans votre propre UI, pour vérifier si les données doivent être mises à jour avant d'effectuer une opération coûteuse ou pour fournir la même instance SafetySourceData à Safety Center avec quelques modifications ou avec une nouvelle instance SafetyEvent. Elle est également utile pour les tests.

Utilisez ce code pour obtenir les dernières données fournies au centre de sécurité:

SafetySourceData lastDataProvided = safetyCenterManager.getSafetySourceData("MySourceId");

Signaler une erreur

Si vous ne parvenez pas à collecter les données SafetySourceData, vous pouvez signaler l'erreur à Safety Center, qui change la couleur de l'entrée en gris, vide les données mises en cache et affiche un message tel que Impossible de vérifier le paramètre. Vous pouvez également signaler une erreur si la résolution d'une instance de SafetySourceIssue.Action échoue, auquel cas l'erreur les données mises en cache ne sont pas effacées et l'entrée de l'interface utilisateur n'est pas modifiée ; mais un message est est montré à l'utilisateur pour l'informer que quelque chose s'est mal passé.

Vous pouvez fournir l'erreur à l'aide de SafetySourceErrorDetails, qui est composé de:

  • SafetySourceErrorDetails: instance SafetyEvent requise:
// An error has occurred in the background, need to clear the Safety Center data to avoid showing data that may not be valid anymore
SafetyEvent safetyEvent = new SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build();
SafetySourceErrorDetails safetySourceErrorDetails = new SafetySourceErrorDetails(safetyEvent);
safetyCenterManager.reportSafetySourceError("MySourceId", safetySourceErrorDetails);

Répondre à une demande d'actualisation ou de nouvelle analyse

Vous pouvez recevoir un signal du centre de sécurité pour fournir de nouvelles données. Pour répondre à une une demande d'actualisation ou de nouvelle analyse garantit que l'utilisateur consulte l'état actuel qui ouvre le Centre de sécurité et quand il appuie sur le bouton de numérisation.

Cela se fait en recevant une annonce avec l'action suivante:

  • ACTION_REFRESH_SAFETY_SOURCES
    • Valeur de chaîne: android.safetycenter.action.REFRESH_SAFETY_SOURCES
    • Déclenché lorsque le centre de sécurité envoie une demande d'actualisation des données de la source de sécurité d'une application donnée ;
    • Intent protégé qui ne peut être envoyé que par le système
    • Envoyée à toutes les sources de sécurité du fichier de configuration en tant qu'intent explicite et nécessite l'autorisation SEND_SAFETY_CENTER_UPDATE

Les extras suivants sont fournis dans le cadre de cette diffusion:

  • EXTRA_REFRESH_SAFETY_SOURCE_IDS
    • Valeur de chaîne: android.safetycenter.extra.REFRESH_SAFETY_SOURCE_IDS
    • Type de tableau de chaînes (String[]), qui représente les ID sources à actualiser l'application donnée
  • EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE

    • Valeur de la chaîne : android.safetycenter.extra.REFRESH_SAFETY_SOURCES_REQUEST_TYPE
    • Type entier, représente un type de requête @IntDef
    • Doit être l'un des suivants: <ph type="x-smartling-placeholder">
        </ph>
      • EXTRA_REFRESH_REQUEST_TYPE_GET_DATA: demande à la source de fournissent des données assez rapidement, généralement lorsque l'utilisateur ouvre la page.
      • EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA: demande la source. afin de fournir des données aussi récentes que possible, généralement lorsque l'utilisateur appuie sur le bouton de nouvelle recherche
  • EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID

    • Valeur de chaîne : android.safetycenter.extra.REFRESH_SAFETY_SOURCES_BROADCAST_ID
    • Type de chaîne, représente un identifiant unique pour l'actualisation demandée

Pour obtenir un signal du centre de sécurité, implémentez une instance BroadcastReceiver. L'annonce est envoyée avec un BroadcastOptions spécial qui permet au pour démarrer un service de premier plan.

BroadcastReceiver répond à une demande d'actualisation :

public final class SafetySourceReceiver extends BroadcastReceiver {
  // All the safety sources owned by this application.
  private static final String[] ALL_SAFETY_SOURCES = new String[] {"MySourceId1", "…"};
  @Override
  public void onReceive(Context context, Intent intent) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
      // Must be on T or above to interact with Safety Center.
      return;
    }
    String action = intent.getAction();
    if (!SafetyCenterManager.ACTION_REFRESH_SAFETY_SOURCES.equals(action)) {
      return;
    }
    String refreshBroadcastId =
        intent.getStringExtra(SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID);
    if (refreshBroadcastId == null) {
      // Should always be provided.
      return;
    }
    String[] sourceIds =
        intent.getStringArrayExtra(SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCE_IDS);
    if (sourceIds == null) {
      sourceIds = ALL_SAFETY_SOURCES;
    }
    int requestType =
        intent.getIntExtra(
            SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE,
            SafetyCenterManager.EXTRA_REFRESH_REQUEST_TYPE_GET_DATA);
    SafetyCenterManager safetyCenterManager = context.getSystemService(SafetyCenterManager.class);
    if (safetyCenterManager == null) {
      // Should not be null on T.
      return;
    }
    if (!safetyCenterManager.isSafetyCenterEnabled()) {
      // Preferably, no Safety Source code should be run if Safety Center is disabled.
      return;
    }
    SafetyEvent refreshSafetyEvent =
        new SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
            .setRefreshBroadcastId(refreshBroadcastId)
            .build();
    for (String sourceId : sourceIds) {
      SafetySourceData safetySourceData = getSafetySourceDataFor(sourceId, requestType);
      // Set the data (or report an error with reportSafetySourceError, if something went wrong).
      safetyCenterManager.setSafetySourceData(sourceId, safetySourceData, refreshSafetyEvent);
    }
  }
  private SafetySourceData getSafetySourceDataFor(String sourceId, int requestType) {
    switch (requestType) {
      case SafetyCenterManager.EXTRA_REFRESH_REQUEST_TYPE_GET_DATA:
        return getRefreshSafetySourceDataFor(sourceId);
      case SafetyCenterManager.EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA:
        return getRescanSafetySourceDataFor(sourceId);
      default:
    }
    return getRefreshSafetySourceDataFor(sourceId);
  }
  // Data to provide when the user opens the page or on specific events.
  private SafetySourceData getRefreshSafetySourceDataFor(String sourceId) {
    // Get data for the source, if it's a fast operation it could potentially be executed in the
    // receiver directly.
    // Otherwise, it must start some kind of foreground service or expedited job.
    return null;
  }
  // Data to provide when the user pressed the rescan button.
  private SafetySourceData getRescanSafetySourceDataFor(String sourceId) {
    // Could be implemented the same way as getRefreshSafetySourceDataFor, depending on the source's
    // need.
    // Otherwise, could potentially perform a longer task.
    // In which case, it must start some kind of foreground service or expedited job.
    return null;
  }
}

La même instance de BroadcastReceiver dans l'exemple ci-dessus est déclarée dans AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="…">
    <application>
    <!--  -->
        <receiver android:name=".SafetySourceReceiver"
            android:exported="false">
            <intent-filter>
                <action android:name="android.safetycenter.action.REFRESH_SAFETY_SOURCES"/>
            </intent-filter>
        </receiver>
    <!--  -->
    </application>
</manifest>

Idéalement, une source Safety Center est implémentée de manière à appeler SafetyCenterManager lorsque ses données changent. Pour des raisons d'intégrité du système, nous vous recommandons de ne répondre qu'au signal de nouvelle analyse (lorsque l'utilisateur appuie sur le bouton d'analyse) et non lorsque l'utilisateur ouvre le Centre de sécurité. Si cette fonctionnalité est obligatoire, le champ refreshOnPageOpenAllowed="true" du fichier de configuration doit être défini pour que la source reçoive la diffusion dans ces cas.

Répondre au Centre de sécurité lorsqu'il est activé ou désactivé

Vous pouvez répondre à l'activation ou à la désactivation du Centre de sécurité à l'aide de cette action d'intent :

  • ACTION_SAFETY_CENTER_ENABLED_CHANGED
    • Valeur de la chaîne : android.safetycenter.action.SAFETY_CENTER_ENABLED_CHANGED
    • Déclenché lorsque le centre de sécurité est activé ou désactivé lorsque l'appareil est en cours d'exécution
    • Non appelé au démarrage (utilisez ACTION_BOOT_COMPLETED pour cela)
    • Intent protégé qui ne peut être envoyé que par le système
    • Envoyé à toutes les sources de sécurité du fichier de configuration en tant que fichier explicite intent, nécessite l'autorisation SEND_SAFETY_CENTER_UPDATE.
    • Envoyé en tant qu'intent implicite qui nécessite READ_SAFETY_CENTER_STATUS autorisation

Cette action d'intent est utile pour activer ou désactiver les fonctionnalités liées au Centre de sécurité sur l'appareil.

Implémenter des actions de résolution

Une action de résolution est une instance SafetySourceIssue.Action qu'un utilisateur peut résoudre directement depuis l'écran du Centre de sécurité. L'utilisateur appuie sur un bouton d'action et l'instance PendingIntent sur SafetySourceIssue.Action envoyée par source de sécurité est déclenchée, ce qui résout le problème en arrière-plan et envoie une notification au centre de sécurité une fois l'opération terminée.

Pour implémenter des actions de résolution, la source du centre de sécurité peut utiliser un service si l'opération est censée prendre un certain temps (PendingIntent.getService) ou un broadcast receiver (PendingIntent.getBroadcast).

Utilisez ce code pour envoyer un problème de résolution au centre de sécurité:

Intent resolveIssueBroadcastIntent =
    new Intent("my.package.name.MY_RESOLVING_ACTION").setClass(ResolveActionReceiver.class);
PendingIntent resolveIssue =
    PendingIntent.getBroadcast(
        context, requestCode, resolveIssueBroadcastIntent, PendingIntent.FLAG_IMMUTABLE);
SafetySourceData safetySourceData =
    new SafetySourceData.Builder()
        .setStatus(
            new SafetySourceStatus.Builder(
                    "title", "summary", SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION)
                .setPendingIntent(redirectToMyScreen)
                .build())
        .addIssue(
            new SafetySourceIssue.Builder(
                    "MyIssueId",
                    "title",
                    "summary",
                    SafetySourceData.SEVERITY_LEVEL_RECOMMENDATION,
                    "MyIssueTypeId")
                .setIssueCategory(SafetySourceIssue.ISSUE_CATEGORY_DEVICE)
                .addAction(
                    new SafetySourceIssue.Action.Builder(
                            "MyIssueActionId", "label", resolveIssue)
                        .setWillResolve(true)
                        .build())
                .build())
        .build();
SafetyEvent safetyEvent = new SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build();
safetyCenterManager.setSafetySourceData("MySourceId", safetySourceData, safetyEvent);

BroadcastReceiver résout l'action:

public final class ResolveActionReceiver extends BroadcastReceiver {
  private static final String MY_RESOLVING_ACTION = "my.package.name.MY_RESOLVING_ACTION";
  @Override
  public void onReceive(Context context, Intent intent) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
      // Must be on T or above to interact with Safety Center.
      return;
    }
    String action = intent.getAction();
    if (!MY_RESOLVING_ACTION.equals(action)) {
      return;
    }
    SafetyCenterManager safetyCenterManager = context.getSystemService(SafetyCenterManager.class);
    if (safetyCenterManager == null) {
      // Should not be null on T.
      return;
    }
    if (!safetyCenterManager.isSafetyCenterEnabled()) {
      // Preferably, no Safety Source code should be run if Safety Center is disabled.
      return;
    }
    resolveTheIssue();
    SafetyEvent resolveActionSafetyEvent =
        new SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_SUCCEEDED)
            .setSafetySourceIssueId("MyIssueId")
            .setSafetySourceIssueActionId("MyIssueActionId")
            .build();
    SafetySourceData dataWithoutTheIssue = ;
    // Set the data (or report an error with reportSafetySourceError and
    // SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED, if something went wrong).
    safetyCenterManager.setSafetySourceData("MySourceId", dataWithoutTheIssue, resolveActionSafetyEvent);
  }

  private void resolveTheIssue() {
    // Resolves the issue for the user. Given this a BroadcastReceiver, this should be a fast action.
    // Otherwise, a foreground service and PendingIntent.getService should be used instead (or a job
    // could be scheduled here, too).
  }
}

La même instance de BroadcastReceiver dans l'exemple ci-dessus est déclarée dans AndroidManifest.xml:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="…">
    <application>
    <!--  -->
        <receiver android:name=".ResolveActionReceiver"
            android:exported="false">
            <intent-filter>
                <action android:name="my.package.name.MY_RESOLVING_ACTION"/>
            </intent-filter>
        </receiver>
    <!--  -->
    </application>
</manifest>

Répondre aux problèmes de refus

Vous pouvez spécifier une instance PendingIntent qui peut être déclenchée lorsqu'un L'instance SafetySourceIssue est fermée. Le centre de sécurité gère ces problèmes abandons:

  • Si une source envoie un problème, un utilisateur peut le fermer sur l'écran du Centre de sécurité en appuyant sur le bouton de fermeture (un bouton X sur la fiche d'avertissement).
  • Lorsqu'un utilisateur ignore un problème, s'il persiste, il ne s'affiche plus dans l'UI.
  • Les fermetures persistantes sur un disque persistent pendant le redémarrage de l'appareil.
  • Si la source du centre de sécurité cesse de signaler un problème, puis indique le problème à nouveau ultérieurement, le problème réapparaît. Cela permet de gérer les situations où un utilisateur voit un avertissement, le ferme, puis prend une mesure qui devrait atténuer le problème, mais que l'utilisateur recommence à faire quelque chose qui provoque un problème similaire. La carte d'avertissement devrait alors réapparaître.
  • Les avertissements jaunes et rouges réapparaissent tous les 180 jours, à moins que l'utilisateur n'ait les a ignorés plusieurs fois.

La source n'a pas besoin de comportements supplémentaires, sauf dans les cas suivants:

  • La source tente d'implémenter ce comportement différemment, par exemple, en ne réexécutant jamais le problème.
  • La source tente de l'utiliser comme rappel, par exemple pour consigner les informations.

Fournir des données pour plusieurs utilisateurs/profils

L'API SafetyCenterManager peut être utilisée par tous les utilisateurs et tous les profils. Pour plus en savoir plus, consultez la page Building Multiuser-Aware Applications. Context qui fournit SafetyCenterManager est associé à un UserHandle L'instance SafetyCenterManager renvoyée interagit donc avec l'instance Centre de sécurité pour cette instance UserHandle. Par défaut, Context est associé à l'utilisateur en cours d'exécution, mais il est possible de créer une instance pour un autre utilisateur si l'application détient les autorisations INTERACT_ACROSS_USERS et INTERACT_ACROSS_USERS_FULL. Cet exemple montre comment passer un appel pour plusieurs utilisateurs/profils:

Context userContext = context.createContextAsUser(userHandle, 0);
SafetyCenterManager userSafetyCenterManager = userContext.getSystemService(SafetyCenterManager.class);
if (userSafetyCenterManager == null) {
  // Should not be null on T.
  return;
}
// Calls to userSafetyCenterManager will provide data for the given userHandle

Chaque utilisateur de l'appareil peut disposer de plusieurs profils gérés. Le Centre de sécurité fournit des données différentes pour chaque utilisateur, mais fusionne les données de tous les profils gérés associés à un utilisateur donné.

Lorsque profile="all_profiles" est défini pour la source dans le fichier de configuration, voici ce qui se produit:

  • Il existe une entrée d'interface utilisateur pour l'utilisateur (parent du profil) et tous ses profils gérés associés (qui utilisent des instances titleForWork).
  • Le signal d'actualisation ou de nouvelle analyse est envoyé pour le parent du profil et tous les profils gérés associés. Le récepteur associé est démarré pour chaque et peut fournir les données associées directement SafetyCenterManager sans avoir à effectuer d'appel dans tous les profils, sauf si le ou l'application est singleUser

  • La source doit fournir des données à l'utilisateur et à toutes ses ressources profils. Les données de chaque entrée de l'UI peuvent varier en fonction du profil.

Tests

vous pouvez accéder à ShadowSafetyCenterManager et l'utiliser dans un test Robolectric.

private static final String MY_SOURCE_ID = "MySourceId";

private final MyClass myClass = ;
private final SafetyCenterManager safetyCenterManager = getApplicationContext().getSystemService(SafetyCenterManager.class);

@Test
public void whenRefreshingData_providesDataToSafetyCenterForMySourceId() {
    shadowOf(safetyCenterManager).setSafetyCenterEnabled(true);
    setupDataForMyClass();

    myClass.refreshData();

    SafetySourceData expectedSafetySourceData = ;
    assertThat(safetyCenterManager.getSafetySourceData(MY_SOURCE_ID)).isEqualTo(expectedSafetySourceData);
    SafetyEvent expectedSafetyEvent = ;
    assertThat(shadowOf(safetyCenterManager).getLastSafetyEvent(MY_SOURCE_ID)).isEqualTo(expectedSafetyEvent);
}

Vous pouvez écrire plus de tests de bout en bout (E2E), mais cela sort du cadre . Pour en savoir plus sur l'écriture de ces tests E2E, consultez la section Tests CTS (CtsSafetyCenterTestCases).

API de test et API internes

Les API internes et les API de test sont destinées à un usage interne et ne sont donc pas décrites dans en détail dans ce guide. Toutefois, il se peut que nous étendions certaines API internes à l'avenir. pour permettre aux OEM de créer leur propre interface utilisateur. Nous mettrons à jour ce guide pour vous des conseils sur la façon de les utiliser.

Autorisations

  • MANAGE_SAFETY_CENTER
    • internal|installer|role
    • Utilisé pour les API internes du centre de sécurité
    • Accordé uniquement à PermissionController et au shell

Application Paramètres

Redirection du centre de sécurité

Par défaut, le Centre de sécurité est accessible via l'application Paramètres avec une nouvelle entrée Sécurité et confidentialité. Si vous utilisez une autre application Paramètres ou si vous l'avez modifiée, vous devrez peut-être personnaliser l'accès au Centre de sécurité.

Lorsque le Centre de sécurité est activé :

  • Code de l'ancienne entrée Confidentialité masquée
  • L'ancienne entrée Sécurité est un code masqué.
  • Nouvelle entrée Sécurité et confidentialité ajoutée code
  • Nouveaux paramètres de sécurité et privacy redirige vers le code du centre de sécurité
  • android.settings.PRIVACY_SETTINGS et android.settings.SECURITY_SETTINGS les actions d'intent sont redirigées vers le centre de sécurité ouvert (code: la sécurité, confidentialité)

Pages sur la sécurité et la confidentialité avancées

L'application Paramètres contient des paramètres supplémentaires sous Autres paramètres de sécurité. et Autres paramètres de confidentialité, disponibles dans le Centre de sécurité:

Sources de sécurité

Le Centre de sécurité s'intègre à un ensemble spécifique de sources de sécurité fournies par l'application Paramètres :

  • Une source de sécurité de l'écran de verrouillage vérifie qu'un écran de verrouillage est configuré avec un code secret (ou une autre mesure de sécurité) pour s'assurer que les informations privées de l'utilisateur sont protégées contre tout accès externe.
  • Une source de sécurité biométrique (masquée par défaut) présente des surfaces à intégrer à un le lecteur d'empreinte digitale ou de visage.

Le code source de ces sources du Centre de sécurité est accessible via Android coder le Réseau de Recherche. Si l'application Paramètres n'est pas modifiée (aucun changement n'est apporté au nom du package, au code source ou au code source qui gère un écran de verrouillage et les données biométriques), cette intégration devrait fonctionner dès la sortie de la boîte. Sinon, certaines modifications peuvent être nécessaires, comme la modification du fichier de configuration pour modifier le nom du package de l'application Paramètres et des sources qui s'intègrent à Safety Center, ainsi que l'intégration. Pour en savoir plus, consultez la section Mettre à jour la configuration fichier et intégration paramètres.

À propos de PendingIntent

Si vous utilisez l'intégration existante du centre de sécurité dans l'application Paramètres sur Android 14 ou version ultérieure, le bug décrit ci-dessous a été corrigé. Dans ce cas, vous n'avez pas besoin de lire cette section.

Lorsque vous êtes certain que le bug n'existe pas, définissez une ressource XML booléenne valeur de configuration dans l'application Paramètres config_isSafetyCenterLockScreenPendingIntentFixed sur true pour désactiver dans le Centre de sécurité.

Solution de contournement avec PendingIntent

Ce bug est dû au fait que les paramètres utilisent les extras d'instance Intent pour déterminer quelle instance fragment pour l'ouvrir. Comme Intent#equals ne prend pas l'instance Intent en compte, l'instance PendingIntent pour l'icône de menu en forme de roue dentée et sont considérées comme égales et permettent d'accéder à la même interface utilisateur (même si elles sont destinés à accéder à une autre interface utilisateur). Ce problème est résolu dans une version QPR en différenciant les instances PendingIntent par code de requête. Vous pouvez également différencier cela à l'aide de Intent#setId.

Sources de sécurité internes

Certaines sources du centre de sécurité sont internes et sont implémentées dans le Application système PermissionController dans le module PermissionController. Ces se comportent comme les sources habituelles du centre de sécurité et ne reçoivent pas de traitement. Le code de ces sources est disponible via le code Android le Réseau de Recherche.

Il s'agit principalement de signaux de confidentialité. Par exemple:

  • Accessibilité
  • Révocation automatique des autorisations des applications inutilisées
  • Accès à la position
  • Outil d'écoute des notifications
  • Infos sur les règles professionnelles