AppOps: Check user permission before audio recording.

Add permission check before audio recording.

Change-Id: I55c8397df3169e031bba951cf180fa8c5f4c4ce0
Conflicts:
media/java/android/media/AudioRecord.java
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index c26f01f..753df44 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -1,4 +1,7 @@
 /*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
  * Copyright (C) 2008 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,6 +21,9 @@
 
 #define LOG_TAG "AudioRecord-JNI"
 
+#include <binder/AppOpsManager.h>
+#include <binder/IPCThreadState.h>
+
 #include <inttypes.h>
 #include <jni.h>
 #include <JNIHelp.h>
@@ -573,6 +579,23 @@
     return frameCount * channelCount * audio_bytes_per_sample(format);
 }
 
+// ----------------------------------------------------------------------------
+// returns the AppOps Permission of package
+static jint android_media_AudioRecord_check_permission(JNIEnv *env,  jobject thiz,
+    jstring packageName) {
+
+    // Convert client name jstring to String16
+    const char16_t *rawClientName = env->GetStringChars(packageName, NULL);
+    jsize rawClientNameLen = env->GetStringLength(packageName);
+    String16 clientName(rawClientName, rawClientNameLen);
+    env->ReleaseStringChars(packageName, rawClientName);
+
+    AppOpsManager appOpsManager;
+
+    // Get UID here for permission checking
+    uid_t clientUid = IPCThreadState::self()->getCallingUid();
+    return appOpsManager.noteOp(AppOpsManager::OP_RECORD_AUDIO, clientUid, clientName);
+}
 
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
@@ -598,6 +621,8 @@
                              "()I",    (void *)android_media_AudioRecord_get_pos_update_period},
     {"native_get_min_buff_size",
                              "(III)I",   (void *)android_media_AudioRecord_get_min_buff_size},
+    {"native_check_permission",
+                             "(Ljava/lang/String;)I", (void *)android_media_AudioRecord_check_permission},
 };
 
 // field names found in android/media/AudioRecord.java
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 540b8d1..8db18d3 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -1,4 +1,7 @@
 /*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
  * Copyright (C) 2008 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -21,6 +24,8 @@
 import java.util.Iterator;
 
 import android.os.Binder;
+import android.app.ActivityThread;
+import android.app.AppOpsManager;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -610,6 +615,10 @@
         return mSessionId;
     }
 
+    private boolean isAudioRecordAllowed() {
+        String packageName = ActivityThread.currentPackageName();
+        return native_check_permission(packageName) == AppOpsManager.MODE_ALLOWED;
+    }
     //---------------------------------------------------------
     // Transport control methods
     //--------------------
@@ -619,6 +628,10 @@
      */
     public void startRecording()
     throws IllegalStateException {
+        if (!isAudioRecordAllowed()) {
+            Log.e(TAG, "User permission denied!");
+            return;
+        }
         if (mState != STATE_INITIALIZED) {
             throw new IllegalStateException("startRecording() called on an "
                     + "uninitialized AudioRecord.");
@@ -642,6 +655,10 @@
      */
     public void startRecording(MediaSyncEvent syncEvent)
     throws IllegalStateException {
+        if (!isAudioRecordAllowed()) {
+            Log.e(TAG, "User permission denied!");
+            return;
+        }
         if (mState != STATE_INITIALIZED) {
             throw new IllegalStateException("startRecording() called on an "
                     + "uninitialized AudioRecord.");
@@ -963,6 +980,8 @@
     static private native final int native_get_min_buff_size(
             int sampleRateInHz, int channelCount, int audioFormat);
 
+    private native final int native_check_permission(String packageName);
+
 
     //---------------------------------------------------------
     // Utility methods