ऑडिट के लिए डेटा का ऐक्सेस

डेटा ऐक्सेस की ऑडिटिंग करके, यह जानकारी पाई जा सकती है कि आपका ऐप्लिकेशन और उसकी डिपेंडेंसी, उपयोगकर्ताओं का निजी डेटा कैसे ऐक्सेस करती हैं. यह प्रोसेस, Android 11 (एपीआई लेवल 30) और उसके बाद के वर्शन वाले डिवाइसों पर उपलब्ध है. इससे, आपको अनचाहे डेटा ऐक्सेस की बेहतर तरीके से पहचान करने में मदद मिलती है. आपका ऐप्लिकेशन, AppOpsManager.OnOpNotedCallback का एक इंस्टेंस रजिस्टर कर सकता है. यह इंस्टेंस, इनमें से किसी भी इवेंट के होने पर कार्रवाइयां कर सकता है:

  • आपके ऐप्लिकेशन का कोड, निजी डेटा ऐक्सेस करता है. यह पता लगाने के लिए कि आपके ऐप्लिकेशन के किस लॉजिकल हिस्से ने इवेंट को ट्रिगर किया है, एट्रिब्यूशन टैग के हिसाब से डेटा ऐक्सेस को ऑडिट किया जा सकता है.
  • डिपेंडेंट लाइब्रेरी या SDK टूल में मौजूद कोड, निजी डेटा को ऐक्सेस करता है.

डेटा ऐक्सेस ऑडिटिंग उस थ्रेड पर शुरू की जाती है जहां डेटा का अनुरोध किया जाता है. इसका मतलब है कि अगर आपके ऐप्लिकेशन में तीसरे पक्ष का कोई SDK टूल या लाइब्रेरी, निजी डेटा ऐक्सेस करने वाले एपीआई को कॉल करती है, तो डेटा ऐक्सेस की ऑडिटिंग की मदद से आपके OnOpNotedCallback को कॉल के बारे में जानकारी मिलती है. आम तौर पर, यह कॉलबैक ऑब्जेक्ट, ऐप्लिकेशन की मौजूदा स्थिति को देखकर यह बता सकता है कि कॉल आपके ऐप्लिकेशन से आया है या SDK टूल से. जैसे, मौजूदा थ्रेड का स्टैक ट्रेस.

डेटा का ऐक्सेस लॉग करना

AppOpsManager.OnOpNotedCallback के किसी इंस्टेंस का इस्तेमाल करके, डेटा ऐक्सेस की ऑडिटिंग करने के लिए, उस कॉम्पोनेंट में कॉलबैक लॉजिक लागू करें जहां आपको डेटा ऐक्सेस की ऑडिटिंग करनी है. जैसे, किसी गतिविधि के onCreate() तरीके या ऐप्लिकेशन के onCreate() तरीके में.

नीचे दिया गया कोड स्निपेट, किसी एक गतिविधि में डेटा ऐक्सेस की ऑडिटिंग के लिए AppOpsManager.OnOpNotedCallback तय करता है:

Kotlin

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)
}

Java

@Override
public void onCreate(@Nullable Bundle savedInstanceState,
        @Nullable PersistableBundle persistentState) {
    AppOpsManager.OnOpNotedCallback appOpsCallback =
            new AppOpsManager.OnOpNotedCallback() {
        private void logPrivateDataAccess(String opCode, String trace) {
            Log.i(MY_APP_TAG, "Private data accessed. " +
                    "Operation: $opCode\nStack Trace:\n$trace");
        }

        @Override
        public void onNoted(@NonNull SyncNotedAppOp syncNotedAppOp) {
            logPrivateDataAccess(syncNotedAppOp.getOp(),
                    Arrays.toString(new Throwable().getStackTrace()));
        }

        @Override
        public void onSelfNoted(@NonNull SyncNotedAppOp syncNotedAppOp) {
            logPrivateDataAccess(syncNotedAppOp.getOp(),
                    Arrays.toString(new Throwable().getStackTrace()));
        }

        @Override
        public void onAsyncNoted(@NonNull AsyncNotedAppOp asyncNotedAppOp) {
            logPrivateDataAccess(asyncNotedAppOp.getOp(),
                    asyncNotedAppOp.getMessage());
        }
    };

    AppOpsManager appOpsManager = getSystemService(AppOpsManager.class);
    if (appOpsManager != null) {
        appOpsManager.setOnOpNotedCallback(getMainExecutor(), appOpsCallback);
    }
}

onAsyncNoted() और onSelfNoted() तरीकों का इस्तेमाल खास स्थितियों में किया जाता है:

  • onAsyncNoted() को तब कॉल किया जाता है, जब आपके ऐप्लिकेशन के एपीआई कॉल के दौरान डेटा ऐक्सेस नहीं होता. सबसे सामान्य उदाहरण यह है कि जब आपका ऐप्लिकेशन किसी लिसनर को रजिस्टर करता है और लिसनर के कॉलबैक को हर बार ट्रिगर करने पर डेटा ऐक्सेस होता है.

    onAsyncNoted() में पास किए गए AsyncNotedOp आर्ग्युमेंट में, getMessage() नाम का एक तरीका शामिल है. इस तरीके से, डेटा ऐक्सेस करने के बारे में ज़्यादा जानकारी मिलती है. जगह की जानकारी के कॉलबैक के मामले में, मैसेज में लिसनर का सिस्टम-आइडेंटिटी-हैश शामिल होता है.

  • onSelfNoted() को बहुत कम मामलों में तब कॉल किया जाता है, जब कोई ऐप्लिकेशन अपना यूआईडी, noteOp() में पास करता है.

एट्रिब्यूशन टैग के हिसाब से डेटा ऐक्सेस को ऑडिट करना

आपके ऐप्लिकेशन के इस्तेमाल के कई मुख्य उदाहरण हो सकते हैं. जैसे, उपयोगकर्ताओं को फ़ोटो खींचने और उन्हें अपने संपर्कों के साथ शेयर करने की सुविधा देना. अगर आपने कई कामों के लिए कोई ऐप्लिकेशन डेवलप किया है, तो उसके डेटा ऐक्सेस का ऑडिट करते समय, अपने ऐप्लिकेशन के हर हिस्से पर एट्रिब्यूशन टैग लागू किया जा सकता है. attributionTag कॉन्टेक्स्ट को onNoted() को कॉल करने के लिए पास किए गए ऑब्जेक्ट में वापस लौटाया जाता है. इससे, डेटा ऐक्सेस को अपने कोड के लॉजिकल हिस्सों तक आसानी से ट्रैक किया जा सकता है.

अपने ऐप्लिकेशन में एट्रिब्यूशन टैग तय करने के लिए, नीचे दिए गए सेक्शन में दिया गया तरीका अपनाएं.

मेनिफ़ेस्ट में एट्रिब्यूशन टैग की जानकारी देना

अगर आपका ऐप्लिकेशन Android 12 (एपीआई लेवल 31) या उसके बाद के वर्शन को टारगेट करता है, तो आपको अपने ऐप्लिकेशन की मेनिफ़ेस्ट फ़ाइल में एट्रिब्यूशन टैग का एलान करना होगा. इसके लिए, यहां दिए गए कोड स्निपेट में दिखाए गए फ़ॉर्मैट का इस्तेमाल करें. अगर आपने किसी ऐसे एट्रिब्यूशन टैग का इस्तेमाल करने की कोशिश की है जिसे आपने अपने ऐप्लिकेशन की मेनिफ़ेस्ट फ़ाइल में एलान नहीं किया है, तो सिस्टम आपके लिए एक null टैग बनाता है और Logcat में एक मैसेज लॉग करता है.

<manifest ...>
    <!-- The value of "android:tag" must be a literal string, and the
         value of "android:label" must be a resource. The value of
         "android:label" is user-readable. -->
    <attribution android:tag="sharePhotos"
                 android:label="@string/share_photos_attribution_label" />
    ...
</manifest>

एट्रिब्यूशन टैग बनाना

डेटा ऐक्सेस करने वाली गतिविधि के onCreate() तरीके में, जैसे कि गतिविधि जहां आपने जगह की जानकारी का अनुरोध किया है या उपयोगकर्ता की संपर्क सूची को ऐक्सेस किया है, createAttributionContext() को कॉल करें. साथ ही, उस एट्रिब्यूशन टैग को पास करें जिसे आपको अपने ऐप्लिकेशन के किसी हिस्से से जोड़ना है.

यहां दिए गए कोड स्निपेट में, किसी ऐप्लिकेशन के फ़ोटो-जगह की जानकारी शेयर करने वाले हिस्से के लिए एट्रिब्यूशन टैग बनाने का तरीका बताया गया है:

Kotlin

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.
    }
}

Java

public class SharePhotoLocationActivity extends AppCompatActivity {
    private Context attributionContext;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState,
            @Nullable PersistableBundle persistentState) {
        attributionContext = createAttributionContext("sharePhotos");
    }

    public void getLocation() {
        LocationManager locationManager =
                attributionContext.getSystemService(LocationManager.class);
        if (locationManager != null) {
            // Use "locationManager" to access device location information.
        }
    }
}

ऐक्सेस लॉग में एट्रिब्यूशन टैग शामिल करना

अपने AppOpsManager.OnOpNotedCallback कॉलबैक को अपडेट करें, ताकि आपके ऐप्लिकेशन के लॉग में, आपके तय किए गए एट्रिब्यूशन टैग के नाम शामिल हों.

यहां दिया गया कोड स्निपेट, एट्रिब्यूशन टैग को लॉग करने वाला अपडेट किया गया लॉजिक दिखाता है:

Kotlin

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)
    }
}

Java

@Override
public void onCreate(@Nullable Bundle savedInstanceState,
        @Nullable PersistableBundle persistentState) {
    AppOpsManager.OnOpNotedCallback appOpsCallback =
            new AppOpsManager.OnOpNotedCallback() {
        private void logPrivateDataAccess(String opCode,
                String attributionTag, String trace) {
            Log.i("MY_APP_TAG", "Private data accessed. " +
                    "Operation: $opCode\n " +
                    "Attribution Tag:$attributionTag\nStack Trace:\n$trace");
        }

        @Override
        public void onNoted(@NonNull SyncNotedAppOp syncNotedAppOp) {
            logPrivateDataAccess(syncNotedAppOp.getOp(),
                    syncNotedAppOp.getAttributionTag(),
                    Arrays.toString(new Throwable().getStackTrace()));
        }

        @Override
        public void onSelfNoted(@NonNull SyncNotedAppOp syncNotedAppOp) {
            logPrivateDataAccess(syncNotedAppOp.getOp(),
                    syncNotedAppOp.getAttributionTag(),
                    Arrays.toString(new Throwable().getStackTrace()));
        }

        @Override
        public void onAsyncNoted(@NonNull AsyncNotedAppOp asyncNotedAppOp) {
            logPrivateDataAccess(asyncNotedAppOp.getOp(),
                    asyncNotedAppOp.getAttributionTag(),
                    asyncNotedAppOp.getMessage());
        }
    };

    AppOpsManager appOpsManager = getSystemService(AppOpsManager.class);
    if (appOpsManager != null) {
        appOpsManager.setNotedAppOpsCollector(appOpsCollector);
    }
}