[veridex] New veridex improvements.

1) Take the type of the receiver on a getClass call.
2) Dedupe reflection uses in precise hidden API finder.
3) Don't do a cheap check that a method is resolved, in case the app
   itself is defining a blacklisted API.

bug: 77513322
Test: m

Change-Id: I8008c2336984e3115b1ae41b53344e0e77091063
diff --git a/tools/veridex/flow_analysis.cc b/tools/veridex/flow_analysis.cc
index a4553f9..736abb7 100644
--- a/tools/veridex/flow_analysis.cc
+++ b/tools/veridex/flow_analysis.cc
@@ -262,8 +262,17 @@
         last_result_ = GetReturnType(instruction.VRegB_35c());
       } else if (method == VeriClass::getClass_) {
         RegisterValue obj = GetRegister(args[0]);
-        last_result_ = RegisterValue(
-            obj.GetSource(), obj.GetDexFileReference(), VeriClass::class_);
+        const VeriClass* cls = obj.GetType();
+        if (cls != nullptr && cls->GetClassDef() != nullptr) {
+          const DexFile::ClassDef* def = cls->GetClassDef();
+          last_result_ = RegisterValue(
+              RegisterSource::kClass,
+              DexFileReference(&resolver_->GetDexFileOf(*cls), def->class_idx_.index_),
+              VeriClass::class_);
+        } else {
+          last_result_ = RegisterValue(
+              obj.GetSource(), obj.GetDexFileReference(), VeriClass::class_);
+        }
       } else if (method == VeriClass::loadClass_) {
         RegisterValue value = GetRegister(args[1]);
         last_result_ = RegisterValue(
diff --git a/tools/veridex/hidden_api_finder.cc b/tools/veridex/hidden_api_finder.cc
index b1ae7dd..8c6139f 100644
--- a/tools/veridex/hidden_api_finder.cc
+++ b/tools/veridex/hidden_api_finder.cc
@@ -31,11 +31,8 @@
 void HiddenApiFinder::CheckMethod(uint32_t method_id,
                                   VeridexResolver* resolver,
                                   MethodReference ref) {
-  // Cheap check that the method is resolved. If it is, we know it's not in
-  // a restricted list.
-  if (resolver->GetMethod(method_id) != nullptr) {
-    return;
-  }
+  // Note: we always query whether a method is in a list, as the app
+  // might define blacklisted APIs (which won't be used at runtime).
   std::string name = HiddenApi::GetApiMethodName(resolver->GetDexFile(), method_id);
   if (hidden_api_.IsInRestrictionList(name)) {
     method_locations_[name].push_back(ref);
@@ -45,11 +42,8 @@
 void HiddenApiFinder::CheckField(uint32_t field_id,
                                  VeridexResolver* resolver,
                                  MethodReference ref) {
-  // Cheap check that the field is resolved. If it is, we know it's not in
-  // a restricted list.
-  if (resolver->GetField(field_id) != nullptr) {
-    return;
-  }
+  // Note: we always query whether a field is in a list, as the app
+  // might define blacklisted APIs (which won't be used at runtime).
   std::string name = HiddenApi::GetApiFieldName(resolver->GetDexFile(), field_id);
   if (hidden_api_.IsInRestrictionList(name)) {
     field_locations_[name].push_back(ref);
diff --git a/tools/veridex/precise_hidden_api_finder.cc b/tools/veridex/precise_hidden_api_finder.cc
index 2092af3..4ae5769 100644
--- a/tools/veridex/precise_hidden_api_finder.cc
+++ b/tools/veridex/precise_hidden_api_finder.cc
@@ -63,6 +63,7 @@
 
 void PreciseHiddenApiFinder::Dump(std::ostream& os, HiddenApiStats* stats) {
   static const char* kPrefix = "       ";
+  std::map<std::string, std::vector<MethodReference>> uses;
   for (auto kinds : { field_uses_, method_uses_ }) {
     for (auto it : kinds) {
       MethodReference ref = it.first;
@@ -74,19 +75,26 @@
           std::string name(info.second.ToString());
           std::string full_name = cls + "->" + name;
           HiddenApiAccessFlags::ApiList api_list = hidden_api_.GetApiList(full_name);
-          stats->api_counts[api_list]++;
           if (api_list != HiddenApiAccessFlags::kWhitelist) {
-            ++stats->reflection_count;
-            os << "#" << ++stats->count << ": Reflection " << api_list << " " << full_name
-               << " use:";
-            os << std::endl;
-            os << kPrefix << HiddenApi::GetApiMethodName(ref) << std::endl;
-            os << std::endl;
+            uses[full_name].push_back(ref);
           }
         }
       }
     }
   }
+
+  for (auto it : uses) {
+    ++stats->reflection_count;
+    const std::string& full_name = it.first;
+    HiddenApiAccessFlags::ApiList api_list = hidden_api_.GetApiList(full_name);
+    stats->api_counts[api_list]++;
+    os << "#" << ++stats->count << ": Reflection " << api_list << " " << full_name << " use(s):";
+    os << std::endl;
+    for (const MethodReference& ref : it.second) {
+      os << kPrefix << HiddenApi::GetApiMethodName(ref) << std::endl;
+    }
+    os << std::endl;
+  }
 }
 
 }  // namespace art
diff --git a/tools/veridex/resolver.h b/tools/veridex/resolver.h
index 52b15fe..65b2961 100644
--- a/tools/veridex/resolver.h
+++ b/tools/veridex/resolver.h
@@ -79,6 +79,10 @@
     return dex_file_;
   }
 
+  const DexFile& GetDexFileOf(const VeriClass& kls) {
+    return GetResolverOf(kls)->dex_file_;
+  }
+
  private:
   // Return the resolver where `kls` is from.
   VeridexResolver* GetResolverOf(const VeriClass& kls) const;