Dynamic audio policies: JNI support for UID rules

Rename AttributeMatchCriterion to AudioMixMatchCriterion to be consistent
 with the fact that now mixing rules are not always about audio attributes.

AudioSystem JNI: add support for UID-based rules.

Bug 26798796

Change-Id: Icb0f57841c94f410e1fac9ed071a829a26b9a58e
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 8e8f6c3..80f8a64 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -128,11 +128,12 @@
     // other fields unused by JNI
 } gAudioMixingRuleFields;
 
-static jclass gAttributeMatchCriterionClass;
+static jclass gAudioMixMatchCriterionClass;
 static struct {
     jfieldID    mAttr;
+    jfieldID    mIntProp;
     jfieldID    mRule;
-} gAttributeMatchCriterionFields;
+} gAudioMixMatchCriterionFields;
 
 static jclass gAudioAttributesClass;
 static struct {
@@ -1563,22 +1564,32 @@
     }
 
     for (jint i = 0; i < numCriteria; i++) {
-        AttributeMatchCriterion nCriterion;
+        AudioMixMatchCriterion nCriterion;
 
         jobject jCriterion = env->GetObjectArrayElement(jCriteria, i);
 
-        nCriterion.mRule = env->GetIntField(jCriterion, gAttributeMatchCriterionFields.mRule);
+        nCriterion.mRule = env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mRule);
 
-        jobject jAttributes = env->GetObjectField(jCriterion, gAttributeMatchCriterionFields.mAttr);
-        if (nCriterion.mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
-                nCriterion.mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
-            nCriterion.mAttr.mUsage = (audio_usage_t)env->GetIntField(jAttributes,
-                                                       gAudioAttributesFields.mUsage);
-        } else {
-            nCriterion.mAttr.mSource = (audio_source_t)env->GetIntField(jAttributes,
-                                                        gAudioAttributesFields.mSource);
+        const uint32_t match_rule = nCriterion.mRule & ~RULE_EXCLUSION_MASK;
+        switch (match_rule) {
+        case RULE_MATCH_UID:
+            nCriterion.mValue.mUid = env->GetIntField(jCriterion,
+                    gAudioMixMatchCriterionFields.mIntProp);
+            break;
+        case RULE_MATCH_ATTRIBUTE_USAGE:
+        case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: {
+            jobject jAttributes = env->GetObjectField(jCriterion, gAudioMixMatchCriterionFields.mAttr);
+            if (match_rule == RULE_MATCH_ATTRIBUTE_USAGE) {
+                nCriterion.mValue.mUsage = (audio_usage_t)env->GetIntField(jAttributes,
+                        gAudioAttributesFields.mUsage);
+            } else {
+                nCriterion.mValue.mSource = (audio_source_t)env->GetIntField(jAttributes,
+                        gAudioAttributesFields.mSource);
+            }
+            env->DeleteLocalRef(jAttributes);
+            }
+            break;
         }
-        env->DeleteLocalRef(jAttributes);
 
         nAudioMix->mCriteria.add(nCriterion);
         env->DeleteLocalRef(jCriterion);
@@ -1833,12 +1844,14 @@
     gAudioMixingRuleFields.mCriteria = GetFieldIDOrDie(env, audioMixingRuleClass, "mCriteria",
                                                        "Ljava/util/ArrayList;");
 
-    jclass attributeMatchCriterionClass =
-                FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule$AttributeMatchCriterion");
-    gAttributeMatchCriterionClass = MakeGlobalRefOrDie(env, attributeMatchCriterionClass);
-    gAttributeMatchCriterionFields.mAttr = GetFieldIDOrDie(env, attributeMatchCriterionClass, "mAttr",
+    jclass audioMixMatchCriterionClass =
+                FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion");
+    gAudioMixMatchCriterionClass = MakeGlobalRefOrDie(env,audioMixMatchCriterionClass);
+    gAudioMixMatchCriterionFields.mAttr = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mAttr",
                                                        "Landroid/media/AudioAttributes;");
-    gAttributeMatchCriterionFields.mRule = GetFieldIDOrDie(env, attributeMatchCriterionClass, "mRule",
+    gAudioMixMatchCriterionFields.mIntProp = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mIntProp",
+                                                       "I");
+    gAudioMixMatchCriterionFields.mRule = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mRule",
                                                        "I");
 
     jclass audioAttributesClass = FindClassOrDie(env, "android/media/AudioAttributes");
diff --git a/media/java/android/media/audiopolicy/AudioMixingRule.java b/media/java/android/media/audiopolicy/AudioMixingRule.java
index 54543ec..e197141 100644
--- a/media/java/android/media/audiopolicy/AudioMixingRule.java
+++ b/media/java/android/media/audiopolicy/AudioMixingRule.java
@@ -42,7 +42,7 @@
 @SystemApi
 public class AudioMixingRule {
 
-    private AudioMixingRule(int mixType, ArrayList<AttributeMatchCriterion> criteria) {
+    private AudioMixingRule(int mixType, ArrayList<AudioMixMatchCriterion> criteria) {
         mCriteria = criteria;
         mTargetMixType = mixType;
     }
@@ -91,21 +91,21 @@
     public static final int RULE_EXCLUDE_UID =
             RULE_EXCLUSION_MASK | RULE_MATCH_UID;
 
-    static final class AttributeMatchCriterion {
+    static final class AudioMixMatchCriterion {
         final AudioAttributes mAttr;
-        final Integer mIntProp;
+        final int mIntProp;
         final int mRule;
 
         /** input parameters must be valid */
-        AttributeMatchCriterion(AudioAttributes attributes, int rule) {
+        AudioMixMatchCriterion(AudioAttributes attributes, int rule) {
             mAttr = attributes;
-            mIntProp = null;
+            mIntProp = Integer.MIN_VALUE;
             mRule = rule;
         }
         /** input parameters must be valid */
-        AttributeMatchCriterion(Integer intProp, int rule) {
+        AudioMixMatchCriterion(Integer intProp, int rule) {
             mAttr = null;
-            mIntProp = intProp;
+            mIntProp = intProp.intValue();
             mRule = rule;
         }
 
@@ -125,10 +125,10 @@
                 dest.writeInt(mAttr.getCapturePreset());
                 break;
             case RULE_MATCH_UID:
-                dest.writeInt(mIntProp.intValue());
+                dest.writeInt(mIntProp);
                 break;
             default:
-                Log.e("AttributeMatchCriterion", "Unknown match rule" + match_rule
+                Log.e("AudioMixMatchCriterion", "Unknown match rule" + match_rule
                         + " when writing to Parcel");
                 dest.writeInt(-1);
             }
@@ -137,8 +137,8 @@
 
     private final int mTargetMixType;
     int getTargetMixType() { return mTargetMixType; }
-    private final ArrayList<AttributeMatchCriterion> mCriteria;
-    ArrayList<AttributeMatchCriterion> getCriteria() { return mCriteria; }
+    private final ArrayList<AudioMixMatchCriterion> mCriteria;
+    ArrayList<AudioMixMatchCriterion> getCriteria() { return mCriteria; }
 
     @Override
     public int hashCode() {
@@ -205,7 +205,7 @@
      */
     @SystemApi
     public static class Builder {
-        private ArrayList<AttributeMatchCriterion> mCriteria;
+        private ArrayList<AudioMixMatchCriterion> mCriteria;
         private int mTargetMixType = AudioMix.MIX_TYPE_INVALID;
 
         /**
@@ -213,7 +213,7 @@
          */
         @SystemApi
         public Builder() {
-            mCriteria = new ArrayList<AttributeMatchCriterion>();
+            mCriteria = new ArrayList<AudioMixMatchCriterion>();
         }
 
         /**
@@ -378,10 +378,10 @@
                 throw new IllegalArgumentException("Incompatible rule for mix");
             }
             synchronized (mCriteria) {
-                Iterator<AttributeMatchCriterion> crIterator = mCriteria.iterator();
+                Iterator<AudioMixMatchCriterion> crIterator = mCriteria.iterator();
                 final int match_rule = rule & ~RULE_EXCLUSION_MASK;
                 while (crIterator.hasNext()) {
-                    final AttributeMatchCriterion criterion = crIterator.next();
+                    final AudioMixMatchCriterion criterion = crIterator.next();
                     switch (match_rule) {
                         case RULE_MATCH_ATTRIBUTE_USAGE:
                             // "usage"-based rule
@@ -413,7 +413,7 @@
                             break;
                         case RULE_MATCH_UID:
                             // "usage"-based rule
-                            if (criterion.mIntProp.intValue() == intProp.intValue()) {
+                            if (criterion.mIntProp == intProp.intValue()) {
                                 if (criterion.mRule == rule) {
                                     // rule already exists, we're done
                                     return this;
@@ -431,10 +431,10 @@
                 switch (match_rule) {
                     case RULE_MATCH_ATTRIBUTE_USAGE:
                     case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
-                        mCriteria.add(new AttributeMatchCriterion(attrToMatch, rule));
+                        mCriteria.add(new AudioMixMatchCriterion(attrToMatch, rule));
                         break;
                     case RULE_MATCH_UID:
-                        mCriteria.add(new AttributeMatchCriterion(intProp, rule));
+                        mCriteria.add(new AudioMixMatchCriterion(intProp, rule));
                         break;
                     default:
                         throw new IllegalStateException("Unreachable code in addRuleInternal()");
diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
index 5ad6126..5d2bac0 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -17,7 +17,7 @@
 package android.media.audiopolicy;
 
 import android.media.AudioFormat;
-import android.media.audiopolicy.AudioMixingRule.AttributeMatchCriterion;
+import android.media.audiopolicy.AudioMixingRule.AudioMixMatchCriterion;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
@@ -86,9 +86,9 @@
             dest.writeInt(mix.getFormat().getEncoding());
             dest.writeInt(mix.getFormat().getChannelMask());
             // write mix rules
-            final ArrayList<AttributeMatchCriterion> criteria = mix.getRule().getCriteria();
+            final ArrayList<AudioMixMatchCriterion> criteria = mix.getRule().getCriteria();
             dest.writeInt(criteria.size());
-            for (AttributeMatchCriterion criterion : criteria) {
+            for (AudioMixMatchCriterion criterion : criteria) {
                 criterion.writeToParcel(dest);
             }
         }
@@ -150,8 +150,8 @@
             textDump += "  channels=0x";
             textDump += Integer.toHexString(mix.getFormat().getChannelMask()).toUpperCase() +"\n";
             // write mix rules
-            final ArrayList<AttributeMatchCriterion> criteria = mix.getRule().getCriteria();
-            for (AttributeMatchCriterion criterion : criteria) {
+            final ArrayList<AudioMixMatchCriterion> criteria = mix.getRule().getCriteria();
+            for (AudioMixMatchCriterion criterion : criteria) {
                 switch(criterion.mRule) {
                     case AudioMixingRule.RULE_EXCLUDE_ATTRIBUTE_USAGE:
                         textDump += "  exclude usage ";
@@ -171,11 +171,11 @@
                         break;
                     case AudioMixingRule.RULE_MATCH_UID:
                         textDump += "  match UID ";
-                        textDump += criterion.mIntProp.toString();
+                        textDump += criterion.mIntProp;
                         break;
                     case AudioMixingRule.RULE_EXCLUDE_UID:
                         textDump += "  exclude UID ";
-                        textDump += criterion.mIntProp.toString();
+                        textDump += criterion.mIntProp;
                         break;
                     default:
                         textDump += "invalid rule!";