Add initialization behavior to libandroidicu

The first step towards removing the libicuandroid_utils
static library. The static library puts initialization
behavior / path knowledge into various binaries that
also use libandroidicu. Moving the initialization behavior
into the dynamic libandroidicu removes path knowledge
(improving encapsulation) and reduces the library count
by one.

Bug: 120493361
Test: regenerate / build only
Change-Id: I0dff682ab733a23983907f69970ec687cdd8ddac
diff --git a/libandroidicu/Android.bp b/libandroidicu/Android.bp
index aa531f2..d4249b2 100644
--- a/libandroidicu/Android.bp
+++ b/libandroidicu/Android.bp
@@ -13,13 +13,20 @@
 // limitations under the License.
 cc_library {
     name: "libandroidicu",
-    srcs: [], // Empty source. The library consists of libandroidicu_static only.
+
+    // Most code is imported via libandroidicu_static.
+    srcs: [
+        "aicu/AIcu.cpp",
+    ],
     host_supported: true,
     unique_host_soname: true,
+
+    // include/aicu/: extra utility APIs added by android
     // include/unicode/: Includes modified C headers from ICU4C,
     //                   but excludes C++ headers.
     // include/uconfig_local.h: local configuration specific for libandroidicu
     export_include_dirs: ["include"],
+
     // The implementation of libandroidicu depends on libicuuc and and libicui18n,
     // but we need to export the headers in include/.
     //
@@ -35,6 +42,7 @@
     shared_libs: [
         "libicuuc",
         "libicui18n",
+        "liblog",
     ],
     stubs: {
         symbol_file: "libandroidicu.map.txt",
diff --git a/libandroidicu/aicu/AIcu.cpp b/libandroidicu/aicu/AIcu.cpp
new file mode 100644
index 0000000..1a9652c
--- /dev/null
+++ b/libandroidicu/aicu/AIcu.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aicu/AIcu.h>
+
+#include "unicode/putil.h"
+#include "unicode/uclean.h"
+#include "unicode/utypes.h"
+#include "utils/Log.h"
+
+#include <stdlib.h>
+
+void AIcu_initializeIcuOrDie() {
+    const char* runtimeModulePathPrefix = getenv("ANDROID_RUNTIME_ROOT");
+    LOG_ALWAYS_FATAL_IF(runtimeModulePathPrefix == NULL,
+            "ANDROID_RUNTIME_ROOT environment variable not set");
+
+    char buf[256];
+    const int num_written = snprintf(buf, sizeof(buf), "%s/etc/icu/", runtimeModulePathPrefix);
+    LOG_ALWAYS_FATAL_IF((num_written < 0 || static_cast<size_t>(num_written) >= sizeof(buf)),
+            "Unable to construct ICU path.");
+
+    u_setDataDirectory(buf);
+    UErrorCode status = U_ZERO_ERROR;
+
+    // u_setDataDirectory doesn't try doing anything with the directory we gave
+    // it, so we'll have to call u_init to make sure it was successful.
+    u_init(&status);
+    LOG_ALWAYS_FATAL_IF(!U_SUCCESS(status), "Failed to initialize ICU %s", u_errorName(status));
+}
diff --git a/libandroidicu/aicu/README.android b/libandroidicu/aicu/README.android
new file mode 100644
index 0000000..0077bb9
--- /dev/null
+++ b/libandroidicu/aicu/README.android
@@ -0,0 +1 @@
+This directory contains extra functions that help with using ICU4C on Android.
diff --git a/libandroidicu/aicu/extra_function_names.txt b/libandroidicu/aicu/extra_function_names.txt
new file mode 100644
index 0000000..95832c1
--- /dev/null
+++ b/libandroidicu/aicu/extra_function_names.txt
@@ -0,0 +1,3 @@
+# Add extra function names here to have them included in the global symbols
+# file during code generation.
+AIcu_initializeIcuOrDie
diff --git a/libandroidicu/include/aicu/AIcu.h b/libandroidicu/include/aicu/AIcu.h
new file mode 100644
index 0000000..e0a0fe1
--- /dev/null
+++ b/libandroidicu/include/aicu/AIcu.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AICU_H
+#define AICU_H
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+// Initializes ICU using the best available data files or dies trying.
+// This must be called when the process is single threaded.
+void AIcu_initializeIcuOrDie();
+
+__END_DECLS
+
+#endif  // AICU_H
+
diff --git a/libandroidicu/libandroidicu.map.txt b/libandroidicu/libandroidicu.map.txt
index fa68a24..aca38cc 100644
--- a/libandroidicu/libandroidicu.map.txt
+++ b/libandroidicu/libandroidicu.map.txt
@@ -985,6 +985,7 @@
     utrans_transIncrementalUChars_android;
     utrans_transUChars_android;
     utrans_unregisterID_android;
+    AIcu_initializeIcuOrDie;
   local:
     *;
 };
\ No newline at end of file
diff --git a/tools/icu4c_srcgen/generate_libandroidicu.py b/tools/icu4c_srcgen/generate_libandroidicu.py
index 9b1914a..c69ca73 100755
--- a/tools/icu4c_srcgen/generate_libandroidicu.py
+++ b/tools/icu4c_srcgen/generate_libandroidicu.py
@@ -60,10 +60,13 @@
     return JINJA_ENV.get_template('shim.cpp.j2').render(data)
 
 
-def generate_symbol_txt(functions):
-    """Generates the symbol txt file  from the given functions."""
+def generate_symbol_txt(shim_functions, extra_function_names):
+    """Generates the symbol txt file from the given functions."""
     data = {
-        'functions': functions,
+        # Each shim_function is given an _android suffix.
+        'shim_functions' : shim_functions,
+        # Each extra function name is included as given.
+        'extra_function_names': extra_function_names,
     }
     return JINJA_ENV.get_template('libandroidicu.map.txt.j2').render(data)
 
@@ -91,10 +94,15 @@
               'w') as out_file:
         out_file.write(generate_shim(functions, includes).encode('utf8'))
 
-    with open(android_path(
-        'external/icu/libandroidicu/libandroidicu.map.txt'),
+    with open(android_path('external/icu/libandroidicu/aicu/extra_function_names.txt'),
+              'r') as in_file:
+        extra_function_names = [
+                line.strip() for line in in_file.readlines() if not line.startswith('#')
+        ]
+
+    with open(android_path('external/icu/libandroidicu/libandroidicu.map.txt'),
               'w') as out_file:
-        out_file.write(generate_symbol_txt(functions).encode('utf8'))
+        out_file.write(generate_symbol_txt(functions, extra_function_names).encode('utf8'))
 
     for path in parser.header_paths_to_copy:
         basename = os.path.basename(path)
diff --git a/tools/icu4c_srcgen/jinja_templates/libandroidicu.map.txt.j2 b/tools/icu4c_srcgen/jinja_templates/libandroidicu.map.txt.j2
index ddfcd84..cf94611 100644
--- a/tools/icu4c_srcgen/jinja_templates/libandroidicu.map.txt.j2
+++ b/tools/icu4c_srcgen/jinja_templates/libandroidicu.map.txt.j2
@@ -17,9 +17,12 @@
 #
 LIBANDROIDICU_EXTERNAL_1 {
   global:
-{% for func in functions %}
+{% for func in shim_functions %}
     {{ func.name }}_android;
 {% endfor %}
+{% for extra_func_name in extra_function_names %}
+    {{ extra_func_name }};
+{% endfor %}
   local:
     *;
 };