9

Audit access to data  |  Android Developers

 3 years ago
source link: https://developer.android.com/guide/topics/data/audit-access
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Audit access to databookmark_border

You can gain insights into how your app and its dependencies access private data from users by performing data access auditing. This process, available on devices that run Android 11 (API level 30) and higher, allows you to better identify potentially unexpected data access. Your app can register an instance of AppOpsManager.OnOpNotedCallback, which can perform actions each time one of the following events occurs:

  • Your app's code accesses private data. To help you determine which logical part of your app invoked the event, you can audit data access by attribution tag.
  • Code in a dependent library or SDK accesses private data.

Data access auditing is invoked on the thread where the data request takes place. This means that, if a 3rd-party SDK or library in your app calls an API that accesses private data, data access auditing allows your OnOpNotedCallback to examine information about the call. Usually, this callback object can tell whether the call came from your app or the SDK by looking at the app's current status, such as the current thread's stack trace.

Log access of data

To perform data access auditing using an instance of AppOpsManager.OnOpNotedCallback, implement the callback logic in the component where you intend to audit data access, such as within an activity's onCreate() method.

Note: If your app accesses data in multiple components, such as in a foreground service and in a background task, create a custom subclass of Application, and define AppOpsManager.OnOpNotedCallback in the onCreate() method of your subclass.

The following code snippet defines an AppOpsManager.OnOpNotedCallback for auditing data access within a single activity:

override fun onCreate(savedInstanceState: Bundle?) {
    val appOpsCallback = object : AppOpsManager.OnOpNotedCallback() {
        private fun logPrivateDataAccess(opCode: String, trace: String) {
            Log.i(MY_APP_TAG, "Private data accessed. " +
                    "Operation: $opCode\nStack Trace:\n$trace")
        }

override fun onNoted(syncNotedAppOp: SyncNotedAppOp) {
            logPrivateDataAccess(
                    syncNotedAppOp.op, Throwable().stackTrace.toString())
        }

override fun onSelfNoted(syncNotedAppOp: SyncNotedAppOp) {
            logPrivateDataAccess(
                    syncNotedAppOp.op, Throwable().stackTrace.toString())
        }

override fun onAsyncNoted(asyncNotedAppOp: AsyncNotedAppOp) {
            logPrivateDataAccess(asyncNotedAppOp.op, asyncNotedAppOp.message)
        }
    }

val appOpsManager =
            getSystemService(AppOpsManager::class.java) as AppOpsManager
    appOpsManager.setOnOpNotedCallback(mainExecutor, appOpsCallback)
}

The onAsyncNoted() and onSelfNoted() methods are called in specific situations:

  • onAsyncNoted() is called if the data access doesn't happen during your app's API call. The most common example is when your app registers a listener and the data access happens each time the listener's callback is invoked.

    The AsyncNotedOp argument that's passed into onAsyncNoted() contains a method called getMessage(). This method provides more information about the data access. In the case of the location callbacks, the message contains the system-identity-hash of the listener.

  • onSelfNoted() is called in the very rare case when an app passes its own UID into noteOp().

Audit data access by attribution tag

Your app might have several primary use cases, such as allowing users to capture photos and share these photos with their contacts. If you develop such a multi-purpose app, you can apply an attribution tag to each part of your app when you audit its data access. The attributionTag context is returned back in the objects passed to the calls to onNoted(). This helps you more easily trace data access back to logical parts of your code.

To define attribution tags in your app, complete the steps in the following sections.

Create attribution tags

In the onCreate() method of the activity where you access data, such as the activity where you request location or access the user's list of contacts, call createAttributionContext(), passing in the attribution tag that you wish to associate with a part of your app.

The following code snippet demonstrates how to create an attribution tag for a "photo location sharing" part of an app:

class SharePhotoLocationActivity : AppCompatActivity() {
    lateinit var attributionContext: Context

override fun onCreate(savedInstanceState: Bundle?) {
        attributionContext = createAttributionContext("sharePhotos")
    }

fun getLocation() {
        val locationManager = attributionContext.getSystemService(
                LocationManager::class.java) as LocationManager
        // Use "locationManager" to access device location information.
    }
}

Include attribution tags in access logs

Update your AppOpsManager.OnOpNotedCallback callback so that your app's logs include the names of the attribution tags that you've defined.

Note: If the return value for the attribution tag is null, this means that the current Context object is associated with the main part of your app.

The following code snippet shows updated logic that logs attribution tags:

val appOpsCallback = object : AppOpsManager.OnOpNotedCallback() {
    private fun logPrivateDataAccess(
            opCode: String, attributionTag: String, trace: String) {
        Log.i(MY_APP_TAG, "Private data accessed. " +
                    "Operation: $opCode\n " +
                    "Attribution Tag:$attributionTag\nStack Trace:\n$trace")
    }

override fun onNoted(syncNotedAppOp: SyncNotedAppOp) {
        logPrivateDataAccess(syncNotedAppOp.op,
                syncNotedAppOp.attributionTag,
                Throwable().stackTrace.toString())
    }

override fun onSelfNoted(syncNotedAppOp: SyncNotedAppOp) {
        logPrivateDataAccess(syncNotedAppOp.op,
                syncNotedAppOp.attributionTag,
                Throwable().stackTrace.toString())
    }

override fun onAsyncNoted(asyncNotedAppOp: AsyncNotedAppOp) {
        logPrivateDataAccess(asyncNotedAppOp.op,
                asyncNotedAppOp.attributionTag,
                asyncNotedAppOp.message)
    }
}

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK