문제

누군가 나에게 Android 애플리케이션 프레임워크 개발과 관련된 튜토리얼을 알려줄 수 있나요?여기서 제가 특별히 이야기하고 있는 것은 "애플리케이션 프레임워크" (안드로이드 아키텍처의 위에서 두 번째 레이어) 및 앱 개발이 아닙니다.

나는 다음에 관심이 있습니다: 앱이 시스템/프레임워크 API를 호출한 후에는 어떻게 되나요?OS는 해당 앱에 특정 권한이 있는지 어떻게 확인합니까?"애플리케이션 프레임워크"의 어떤 구성요소가 이 검사를 처리합니까?어떤 Java 클래스가 이를 담당합니까?

나는 이러한 Java 클래스를 가지고 놀면서 몇 가지 관찰을 하고 싶습니다.

추신.:권한 모델이 "응용 프로그램 프레임워크" 계층에서 구현된다고 가정합니다.내가 틀렸다면 정정하십시오.

도움이 되었습니까?

해결책

내가 아는 한 프레임워크 개발을 위한 리소스는 제한되어 있으며, 사용 가능한 대부분의 리소스는 다양한 블로그와 메일링 리스트에 분산되어 있습니다.시작하려면 오픈 소스 프로젝트 사이트를 추천합니다. source.android.com.여기에는 작업 수행 방법에 대한 제한된 문서가 포함되어 있지만 최소한 오픈 소스 프로젝트 작업을 위한 설정을 제공합니다.그런 다음 공식 메일링 리스트 플랫폼 및 프레임워크 수준 개발과 관련됩니다.다양한 ROM 프로젝트에는 다음과 같은 사이트에 유용한 정보가 있을 수도 있습니다. 사이노겐모드 위키.

그런 다음 프레임워크에서 권한이 구현되는 방법에 대한 특정 질문에 답하십시오.검사를 처리하는 특정 구성 요소는 없으며, 프레임워크의 각 서비스 공급자는 서비스 호출이 진행되도록 허용하기 전에 권한 검사를 수행해야 합니다.이러한 검사에는 시스템 서버의 패키지 관리자와 바인더 IPC 메커니즘이라는 두 가지 중요한 부분이 포함됩니다.패키지 관리자는 애플리케이션 설치를 처리하는 OS 구성 요소입니다.그러면 설치 시 AndroidManifest.xml 파일을 구문 분석하고 사용자에게 권한을 묻는 메시지를 표시하며 특정 앱이 보유한 권한에 대한 레지스트리를 유지 관리합니다.이는 각 애플리케이션이 자체 Linux 사용자 ID로 실행된다는 아이디어를 기반으로 합니다.각 uid에는 권한 목록이 있습니다.

두 번째 부분은 바인더 프로세스 간 통신 메커니즘입니다.바인더는 IPC를 수행하는 객체 지향 방식이지만 일부 보안 기능도 구현합니다.권한과 관련된 가장 중요한 것은 IPC 호출을 받는 쪽에서 호출자의 uid를 확인할 수 있다는 것입니다.권한으로 보호되는 서비스에는 바인더 인터페이스가 있으며 수신되는 모든 요청에 ​​대해 두 가지 작업을 수행합니다.먼저 바인더를 호출하여 호출자의 uid를 가져온 다음 uid와 권한이 부여되었는지 확인하기 위한 권한을 제공하는 시스템 서버를 호출합니다.검사가 정상이면 계속해서 서비스 호출을 실행하고 그렇지 않으면 보안 예외가 발생합니다.

소스 코드를 살펴보면 진동기 서비스에 대한 간단한 호출부터 시작합니다.(아래의 모든 코드는 Apache 2.0 라이선스에 따라 Android 오픈 소스 프로젝트에 대한 저작권을 갖습니다.)

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

프레임워크 수준 권한 확인에 대한 구현은 Context 클래스에 속하며 보다 구체적으로 ContextImpl.java 파일이 있습니다.

@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;
    }
}

이는 Binder를 통해 ActivityManagerService에 대한 호출로, 여기서는 다음과 같이 종료됩니다.

/**
 * 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;
}

패키지 관리자 checkUidPermission에 대한 호출은 uid를 부여된 권한 테이블과 일치시키기 위해 조회를 수행하는 것입니다.소스 추적을 계속하려면 관련 파일은 PackageManagerService.java입니다.

단지 연구를 하고 있다면 오픈 소스 프로젝트의 Frameworks/base/에 있는 코드를 직접 살펴보세요.위에서 언급한 모든 파일이 여기에 있습니다.빌드 지침을 따르면 에뮬레이터를 사용하여 변경 사항을 테스트할 수 있습니다.핵심 프레임워크 파일 자체를 수정하지 않으려면 프레임워크 확장을 수행하는 방법에 대한 /device/sample의 샘플을 살펴보세요.즉, 대부분의 권한 관련 API는 애플리케이션 수준에서 사용할 수 있으므로 서비스를 제공하는 애플리케이션을 갖고 이에 대해 자체 권한 확인을 수행하는 것만으로도 성공할 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top