Envrionment provides access to env vars and system properties

When accessing analytics from AGP we need to use Gradle APIs in
order to access system properties and env variables. This CL
expands Envrionment API to support accessing system properties.
Any system property read should use this API.

From the AGP side a Gradle-specific implementation of Environment
is provided and set during initialization.

Bug: 148512507
Test: existing
Change-Id: Ic323c445774a6a4e59d05ddddeae2fdb28d0228b
diff --git a/publisher/src/main/java/com/android/tools/analytics/GoogleAnalyticsPublisher.kt b/publisher/src/main/java/com/android/tools/analytics/GoogleAnalyticsPublisher.kt
index f1cab7f..d47884e 100644
--- a/publisher/src/main/java/com/android/tools/analytics/GoogleAnalyticsPublisher.kt
+++ b/publisher/src/main/java/com/android/tools/analytics/GoogleAnalyticsPublisher.kt
@@ -73,7 +73,7 @@
               CommonMetricsData
                 .majorOsVersion!!)
             .setOsFullVersion(
-              System.getProperty("os.version"))))
+              Environment.instance.getSystemProperty("os.version"))))
     // Set the log source for the Clearcut service. This will be always the
     // same no matter what Android devtool we're logging from.
     .setLogSource(ClientAnalytics.LogRequest.LogSource.ANDROID_STUDIO)
diff --git a/shared/src/main/java/com/android/tools/analytics/AnalyticsPaths.kt b/shared/src/main/java/com/android/tools/analytics/AnalyticsPaths.kt
index e4b04ae..fda67bb 100644
--- a/shared/src/main/java/com/android/tools/analytics/AnalyticsPaths.kt
+++ b/shared/src/main/java/com/android/tools/analytics/AnalyticsPaths.kt
@@ -40,10 +40,10 @@
     // currently can't be shared with AndroidLocation see b/37123089
     var home = Environment.instance.getVariable("ANDROID_SDK_HOME")
     if (Strings.isNullOrEmpty(home)) {
-      home = System.getProperty("ANDROID_SDK_HOME")
+      home = Environment.instance.getSystemProperty("ANDROID_SDK_HOME")
     }
     if (Strings.isNullOrEmpty(home)) {
-      home = Paths.get(System.getProperty("user.home"), ".android").toString()
+      home = Paths.get(Environment.instance.getSystemProperty("user.home")!!, ".android").toString()
     }
     File(home).mkdirs()
     return home!!
diff --git a/shared/src/main/java/com/android/tools/analytics/AnalyticsSettings.kt b/shared/src/main/java/com/android/tools/analytics/AnalyticsSettings.kt
index d3c630b..b4c73c2 100644
--- a/shared/src/main/java/com/android/tools/analytics/AnalyticsSettings.kt
+++ b/shared/src/main/java/com/android/tools/analytics/AnalyticsSettings.kt
@@ -273,9 +273,10 @@
    */
   @JvmStatic
   @JvmOverloads
-  fun initialize(logger: ILogger, scheduler: ScheduledExecutorService? = null) {
+  fun initialize(logger: ILogger, scheduler: ScheduledExecutorService? = null, environment: Environment? = null) {
     synchronized(gate) {
       try {
+        environment?.let { Environment.instance = environment }
         if (instance != null) {
           return
         }
diff --git a/shared/src/main/java/com/android/tools/analytics/CommonMetricsData.kt b/shared/src/main/java/com/android/tools/analytics/CommonMetricsData.kt
index e3aad1f..ec88e84 100644
--- a/shared/src/main/java/com/android/tools/analytics/CommonMetricsData.kt
+++ b/shared/src/main/java/com/android/tools/analytics/CommonMetricsData.kt
@@ -54,7 +54,7 @@
       val jvmArchitecture = jvmArchitecture
       if (jvmArchitecture == ProductDetails.CpuArchitecture.X86) {
 
-        val os = System.getProperty("os.name").toLowerCase()
+        val os = Environment.instance.getSystemProperty("os.name")!!.toLowerCase()
         if (os.startsWith("win")) {
           val w6432 = Environment.instance.getVariable("PROCESSOR_ARCHITEW6432")
           // This is the misleading case: the JVM is 32-bit but the OS
@@ -84,7 +84,7 @@
   @JvmStatic
   val jvmArchitecture: ProductDetails.CpuArchitecture
     get() {
-      val arch = System.getProperty("os.arch")
+      val arch = Environment.instance.getSystemProperty("os.arch")
       return cpuArchitectureFromString(arch)
     }
 
@@ -94,7 +94,7 @@
   @JvmStatic
   val osName: String
     get() {
-      var os: String? = System.getProperty("os.name")
+      var os: String? = Environment.instance.getSystemProperty("os.name")
 
       if (os == null || os.isEmpty()) {
         return "unknown"
@@ -128,7 +128,7 @@
       }
 
       val p = Pattern.compile("(\\d+)\\.(\\d+).*")
-      val osVers = System.getProperty("os.version")
+      val osVers = Environment.instance.getSystemProperty("os.version")
       if (osVers != null && osVers.isNotEmpty()) {
         val m = p.matcher(osVers)
         if (m.matches()) {
diff --git a/shared/src/main/java/com/android/tools/analytics/Environment.kt b/shared/src/main/java/com/android/tools/analytics/Environment.kt
index 8ae0d43..f257a58 100644
--- a/shared/src/main/java/com/android/tools/analytics/Environment.kt
+++ b/shared/src/main/java/com/android/tools/analytics/Environment.kt
@@ -17,14 +17,20 @@
 package com.android.tools.analytics
 
 /**
- * Helper class to create indirection reading environment variables
- * as Java doesn't allow overwriting environment variables for the current process.
- * This is needed to allow overriding the environment variables in tests.
+ * Helper class to create indirection reading environment variables and system properties. This
+ * allows providing custom logic for reading these values. E.g. because Java doesn't allow
+ * overwriting environment variables for the current process, in tests this is used to provide the
+ * environment variables. Also, build system may implement this in a way that is using build system
+ * specific APIs to access system properties and environment variables.
  */
 abstract class Environment {
 
   abstract fun getVariable(name: String): String?
 
+  open fun getSystemProperty(name: String): String? {
+    return System.getProperty(name)
+  }
+
   companion object {
     @JvmStatic
     val SYSTEM: Environment = object : Environment() {
diff --git a/shared/src/test/java/com/android/tools/analytics/AnalyticsPathsTest.kt b/shared/src/test/java/com/android/tools/analytics/AnalyticsPathsTest.kt
index 00108d2..bb3b339 100644
--- a/shared/src/test/java/com/android/tools/analytics/AnalyticsPathsTest.kt
+++ b/shared/src/test/java/com/android/tools/analytics/AnalyticsPathsTest.kt
@@ -44,7 +44,7 @@
     // Test picking the default path ~/.android/ when no environment variable exists.
     EnvironmentFakes.setNoEnvironmentVariable()
     assertEquals(
-      Paths.get(System.getProperty("user.home"), ".android").toString(),
+      Paths.get(Environment.instance.getSystemProperty("user.home")!!, ".android").toString(),
       AnalyticsPaths.getAndEnsureAndroidSettingsHome())
 
     // Test using the ANDROID_SDK_HOME environment variable.
@@ -54,7 +54,7 @@
 
     // Test using the ANDROID_SDK_HOME as a system property.
     val property = "ANDROID_SDK_HOME"
-    val prev = System.getProperty(property)
+    val prev = Environment.instance.getSystemProperty(property)
     System.setProperty(property, customRoot)
     assertEquals(customRoot, AnalyticsPaths.getAndEnsureAndroidSettingsHome())
     if (prev != null) {
@@ -82,7 +82,7 @@
     // Test picking the default path under ~/.android/ when no environment variable exists.
     EnvironmentFakes.setNoEnvironmentVariable()
     assertEquals(
-      Paths.get(System.getProperty("user.home"), ".android", "metrics", "spool").toString(),
+      Paths.get(Environment.instance.getSystemProperty("user.home")!!, ".android", "metrics", "spool").toString(),
       AnalyticsPaths.spoolDirectory)
 
     // Test using the ANDROID_SDK_HOME environment variable.