Question

Quelqu'un peut-il m'indiquer des tutoriels liés au développement du cadre d'application Android? Ici je parle particulièrement de "Framework d'application" (Deuxième couche du haut de l'architecture Android) et non le développement d'applications.

Je suis intéressé par: Que se passe-t-il après une API système / framework d'appel d'application? Comment le système d'exploitation vérifie-t-il si cette application a cette autorisation particulière? Quel composant dans "Application Framework" gère cette vérification? Quelles cours Java en sont responsables?

Je voudrais jouer avec ces cours Java et faire quelques observations.

PS: Je suppose que le modèle d'autorisation est implémenté dans la couche "Framework d'application". Corrigez-moi si je me trompe.

Était-ce utile?

La solution

Pour autant que je sache, des ressources limitées pour le développement des cadres sont à ma connaissance, la plupart de ce qui est disponible est réparti sur différents blogs et listes de diffusion. Pour commencer, je recommanderais le site du projet open source, source.android.com. Il contient une documentation limitée sur la façon de faire les choses, mais fournit au moins la configuration pour travailler avec le projet open source. Alors il y a le listes de diffusion officielles lié au développement du niveau de la plate-forme et du cadre. Les différents projets ROM peuvent également avoir des informations utiles sur des sites tels que le Wiki cyanogène.

Ensuite, pour répondre à votre question spécifique sur la façon dont les autorisations sont mises en œuvre dans le cadre. Il n'y a pas de composant spécifique qui gère les chèques, chaque fournisseur de services dans le framework doit effectuer une vérification d'autorisation avant d'autoriser un appel de service à passer. Il y a deux éléments importants impliqués dans un tel chèque, le gestionnaire de packages du serveur système et le mécanisme IPC de liant. Le gestionnaire de packages est le composant OS qui gère l'installation d'applications. Cela analysera le fichier AndroidManifest.xml lors de l'installation, demandera l'utilisateur pour les autorisations et maintiendra un registre des autorisations d'une application spécifique. Ceci est basé sur l'idée que chaque application s'exécute avec son propre ID utilisateur Linux. Pour chaque UID, il y a une liste d'autorisations.

La deuxième partie est le mécanisme de communication interprète de liant. Le liant est une manière orientée objet d'effectuer IPC mais il implémente également certaines fonctionnalités de sécurité. La plus importante liée aux autorisations est qu'il permet à la fin de réception d'un appel IPC pour vérifier l'UID de l'appelant. Un service protégé par une autorisation aura une interface de liant et fera deux choses pour chaque demande qu'elle reçoit. Il appellera d'abord le classeur pour obtenir l'UID de l'appelant, puis il appellera le serveur système fournissant l'UID et l'autorisation de vérifier s'il a été accordé. Si le chèque est OK, il continuera et exécutera l'appel de service, sinon, il augmentera une exception de sécurité.

Si nous jetons un coup d'œil dans le code source, en commençant par un simple appel au service de vibrateur. (Tout le code ci-dessous est le droit d'auteur du projet Open Source Android sous la licence Apache 2.0).

public void vibrate(long milliseconds, IBinder token) {
    if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
            != PackageManager.PERMISSION_GRANTED) {
        throw new SecurityException("Requires VIBRATE permission");
    }

L'implémentation des vérifications des autorisations de niveau de cadre appartient à la classe de contexte et plus précisément, nous avons le fichier contextimpl.java où

@Override
public int checkCallingOrSelfPermission(String permission) {
    if (permission == null) {
        throw new IllegalArgumentException("permission is null");
    }

    return checkPermission(permission, Binder.getCallingPid(),
            Binder.getCallingUid());
}
@Override
public int checkPermission(String permission, int pid, int uid) {
    if (permission == null) {
        throw new IllegalArgumentException("permission is null");
    }

    try {
        return ActivityManagerNative.getDefault().checkPermission(
                permission, pid, uid);
    } catch (RemoteException e) {
        return PackageManager.PERMISSION_DENIED;
    }
}

C'est un appel à travers le classeur à l'activitéManagerservice où nous nous retrouverons:

/**
 * As the only public entry point for permissions checking, this method
 * can enforce the semantic that requesting a check on a null global
 * permission is automatically denied.  (Internally a null permission
 * string is used when calling {@link #checkComponentPermission} in cases
 * when only uid-based security is needed.)
 * 
 * This can be called with or without the global lock held.
 */
public int checkPermission(String permission, int pid, int uid) {
    if (permission == null) {
        return PackageManager.PERMISSION_DENIED;
    }
    return checkComponentPermission(permission, pid, uid, -1, true);
} 
/**
 * This can be called with or without the global lock held.
 */
int checkComponentPermission(String permission, int pid, int uid,
        int owningUid, boolean exported) {
    // We might be performing an operation on behalf of an indirect binder
    // invocation, e.g. via {@link #openContentUri}.  Check and adjust the
    // client identity accordingly before proceeding.
    Identity tlsIdentity = sCallerIdentity.get();
    if (tlsIdentity != null) {
        Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
                + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
        uid = tlsIdentity.uid;
        pid = tlsIdentity.pid;
    }

    // Root, system server and our own process get to do everything.
    if (uid == 0 || uid == Process.SYSTEM_UID || pid == MY_PID) {
        return PackageManager.PERMISSION_GRANTED;
    }
    // If there is a uid that owns whatever is being accessed, it has
    // blanket access to it regardless of the permissions it requires.
    if (owningUid >= 0 && uid == owningUid) {
        return PackageManager.PERMISSION_GRANTED;
    }
    // If the target is not exported, then nobody else can get to it.
    if (!exported) {
        Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
        return PackageManager.PERMISSION_DENIED;
    }
    if (permission == null) {
        return PackageManager.PERMISSION_GRANTED;
    }
    try {
        return AppGlobals.getPackageManager()
                .checkUidPermission(permission, uid);
    } catch (RemoteException e) {
        // Should never happen, but if it does... deny!
        Slog.e(TAG, "PackageManager is dead?!?", e);
    }
    return PackageManager.PERMISSION_DENIED;
}

L'appel au gestionnaire de packages CheckUIDPermission est ce qui effectuera la recherche pour correspondre à l'UID avec les tableaux des autorisations accordées. Si vous souhaitez continuer à suivre la source, le fichier pertinent est PackageManagerservice.java.

Si vous faites simplement une étude, n'hésitez pas à plonger directement dans le code dans Frameworks / Base / dans le projet open source. Tous les fichiers mentionnés ci-dessus sont là-dedans. Suivez les instructions de construction et vous devriez être en mesure de tester vos modifications à l'aide de l'émulateur. Si vous ne souhaitez pas modifier les fichiers Core Framework eux-mêmes, jetez un œil à l'échantillon dans / périphérique / échantillon sur la façon de faire des extensions de framework. Cela dit, la plupart des API liées à l'autorisation sont disponibles à partir du niveau de demande, vous pouvez donc réussir en ayant une application qui fournit un service et effectuez votre propre autorisation à y vérifier.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top