Merge "liblog: Remove stdbool.h from .cpp files"
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index b504161..5b377ae 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -36,6 +36,7 @@
"builder.cpp",
"images.cpp",
"partition_opener.cpp",
+ "property_fetcher.cpp",
"reader.cpp",
"utility.cpp",
"writer.cpp",
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index a434c93..777743c 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -19,23 +19,17 @@
#include <string.h>
#include <algorithm>
-#include <string_view>
-#include <android-base/properties.h>
#include <android-base/unique_fd.h>
#include "liblp/liblp.h"
+#include "liblp/property_fetcher.h"
#include "reader.h"
#include "utility.h"
namespace android {
namespace fs_mgr {
-std::optional<bool> MetadataBuilder::sABOverride;
-std::optional<bool> MetadataBuilder::sRetrofitDap;
-
-static constexpr std::string_view kDefaultGroup = "default";
-
bool LinearExtent::AddTo(LpMetadata* out) const {
if (device_index_ >= out->block_devices.size()) {
LERROR << "Extent references unknown block device.";
@@ -165,16 +159,27 @@
return nullptr;
}
- // On non-retrofit devices there is only one location for metadata: the
- // super partition. update_engine will remove and resize partitions as
- // needed. On the other hand, for retrofit devices, we'll need to
- // translate block device and group names to update their slot suffixes.
+ // On retrofit DAP devices, modify the metadata so that it is suitable for being written
+ // to the target slot later. We detect retrofit DAP devices by checking the super partition
+ // name and system properties.
+ // See comments for UpdateMetadataForOtherSuper.
auto super_device = GetMetadataSuperBlockDevice(*metadata.get());
- if (GetBlockDevicePartitionName(*super_device) == "super" ||
- !IsRetrofitDynamicPartitionsDevice()) {
- return New(*metadata.get(), &opener);
+ if (GetBlockDevicePartitionName(*super_device) != "super" &&
+ IsRetrofitDynamicPartitionsDevice()) {
+ if (!UpdateMetadataForOtherSuper(metadata.get(), source_slot_number, target_slot_number)) {
+ return nullptr;
+ }
}
+ return New(*metadata.get(), &opener);
+}
+
+// For retrofit DAP devices, there are (conceptually) two super partitions. We'll need to translate
+// block device and group names to update their slot suffixes.
+// (On the other hand, On non-retrofit DAP devices there is only one location for metadata: the
+// super partition. update_engine will remove and resize partitions as needed.)
+bool MetadataBuilder::UpdateMetadataForOtherSuper(LpMetadata* metadata, uint32_t source_slot_number,
+ uint32_t target_slot_number) {
// Clear partitions and extents, since they have no meaning on the target
// slot. We also clear groups since they are re-added during OTA.
metadata->partitions.clear();
@@ -194,7 +199,7 @@
// refers to a target or unknown block device.
LERROR << "Invalid block device for slot " << source_slot_suffix << ": "
<< partition_name;
- return nullptr;
+ return false;
}
std::string new_name =
partition_name.substr(0, partition_name.size() - slot_suffix.size()) +
@@ -203,20 +208,12 @@
auto new_device = source_block_device;
if (!UpdateBlockDevicePartitionName(&new_device, new_name)) {
LERROR << "Partition name too long: " << new_name;
- return nullptr;
+ return false;
}
metadata->block_devices.emplace_back(new_device);
}
- return New(*metadata.get(), &opener);
-}
-
-void MetadataBuilder::OverrideABForTesting(bool ab_device) {
- sABOverride = ab_device;
-}
-
-void MetadataBuilder::OverrideRetrofitDynamicParititonsForTesting(bool retrofit) {
- sRetrofitDap = retrofit;
+ return true;
}
MetadataBuilder::MetadataBuilder() : auto_slot_suffixing_(false) {
@@ -1051,17 +1048,12 @@
}
bool MetadataBuilder::IsABDevice() {
- if (sABOverride.has_value()) {
- return *sABOverride;
- }
- return !android::base::GetProperty("ro.boot.slot_suffix", "").empty();
+ return !IPropertyFetcher::GetInstance()->GetProperty("ro.boot.slot_suffix", "").empty();
}
bool MetadataBuilder::IsRetrofitDynamicPartitionsDevice() {
- if (sRetrofitDap.has_value()) {
- return *sRetrofitDap;
- }
- return android::base::GetBoolProperty("ro.boot.dynamic_partitions_retrofit", false);
+ return IPropertyFetcher::GetInstance()->GetBoolProperty("ro.boot.dynamic_partitions_retrofit",
+ false);
}
bool MetadataBuilder::IsRetrofitMetadata() const {
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index 377ec68..6d27873 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -19,36 +19,40 @@
#include <gtest/gtest.h>
#include <liblp/builder.h>
+#include "mock_property_fetcher.h"
#include "utility.h"
using namespace std;
using namespace android::fs_mgr;
+using ::android::fs_mgr::MockPropertyFetcher;
+using ::testing::_;
+using ::testing::AnyNumber;
using ::testing::ElementsAre;
+using ::testing::NiceMock;
+using ::testing::Return;
+
+static void ResetPropertyFetcher() {
+ IPropertyFetcher::OverrideForTesting(std::make_unique<NiceMock<MockPropertyFetcher>>());
+}
+
+MockPropertyFetcher* GetMockedInstance() {
+ return static_cast<MockPropertyFetcher*>(IPropertyFetcher::GetInstance());
+}
class Environment : public ::testing::Environment {
public:
- void SetUp() override {
- MetadataBuilder::OverrideABForTesting(false);
- MetadataBuilder::OverrideRetrofitDynamicParititonsForTesting(false);
- }
+ void SetUp() override { ResetPropertyFetcher(); }
};
int main(int argc, char** argv) {
- ::testing::AddGlobalTestEnvironment(new Environment);
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
class BuilderTest : public ::testing::Test {
public:
- void SetUp() override {
- MetadataBuilder::OverrideABForTesting(false);
- MetadataBuilder::OverrideRetrofitDynamicParititonsForTesting(false);
- }
- void TearDown() override {
- MetadataBuilder::OverrideABForTesting(false);
- MetadataBuilder::OverrideRetrofitDynamicParititonsForTesting(false);
- }
+ void SetUp() override { ResetPropertyFetcher(); }
+ void TearDown() override { ResetPropertyFetcher(); }
};
TEST_F(BuilderTest, BuildBasic) {
@@ -785,7 +789,9 @@
// A and B slots should be allocated from separate halves of the partition,
// to mitigate allocating too many extents. (b/120433288)
- MetadataBuilder::OverrideABForTesting(true);
+ ON_CALL(*GetMockedInstance(), GetProperty("ro.boot.slot_suffix", _))
+ .WillByDefault(Return("_a"));
+
auto builder = MetadataBuilder::New(device_info, 65536, 2);
ASSERT_NE(builder, nullptr);
Partition* system_a = builder->AddPartition("system_a", 0);
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index a2221ef..3b229bd 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -24,6 +24,7 @@
#include <memory>
#include <optional>
#include <set>
+#include <string_view>
#include "liblp.h"
#include "partition_opener.h"
@@ -37,6 +38,9 @@
static const uint32_t kDefaultPartitionAlignment = 1024 * 1024;
static const uint32_t kDefaultBlockSize = 4096;
+// Name of the default group in a metadata.
+static constexpr std::string_view kDefaultGroup = "default";
+
// Abstraction around dm-targets that can be encoded into logical partition tables.
class Extent {
public:
@@ -196,12 +200,6 @@
return New(device_info, metadata_max_size, metadata_slot_count);
}
- // Used by the test harness to override whether the device is "A/B".
- static void OverrideABForTesting(bool ab_device);
-
- // Used by the test harness to override whether the device is "retrofitting dynamic partitions".
- static void OverrideRetrofitDynamicParititonsForTesting(bool retrofit);
-
// Define a new partition group. By default there is one group called
// "default", with an unrestricted size. A non-zero size will restrict the
// total space used by all partitions in the group.
@@ -347,8 +345,8 @@
const std::vector<Interval>& free_list,
uint64_t sectors_needed) const;
- static std::optional<bool> sABOverride;
- static std::optional<bool> sRetrofitDap;
+ static bool UpdateMetadataForOtherSuper(LpMetadata* metadata, uint32_t source_slot_number,
+ uint32_t target_slot_number);
LpMetadataGeometry geometry_;
LpMetadataHeader header_;
diff --git a/fs_mgr/liblp/include/liblp/property_fetcher.h b/fs_mgr/liblp/include/liblp/property_fetcher.h
new file mode 100644
index 0000000..e73a1f5
--- /dev/null
+++ b/fs_mgr/liblp/include/liblp/property_fetcher.h
@@ -0,0 +1,42 @@
+//
+// Copyright (C) 2019 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.
+//
+
+#pragma once
+
+#include <memory>
+
+namespace android {
+namespace fs_mgr {
+
+class IPropertyFetcher {
+ public:
+ virtual ~IPropertyFetcher() = default;
+ virtual std::string GetProperty(const std::string& key, const std::string& defaultValue) = 0;
+ virtual bool GetBoolProperty(const std::string& key, bool defaultValue) = 0;
+
+ static IPropertyFetcher* GetInstance();
+ static void OverrideForTesting(std::unique_ptr<IPropertyFetcher>&&);
+};
+
+class PropertyFetcher : public IPropertyFetcher {
+ public:
+ ~PropertyFetcher() = default;
+ std::string GetProperty(const std::string& key, const std::string& defaultValue) override;
+ bool GetBoolProperty(const std::string& key, bool defaultValue) override;
+};
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp
index 70dd85f..2990863 100644
--- a/fs_mgr/liblp/io_test.cpp
+++ b/fs_mgr/liblp/io_test.cpp
@@ -23,10 +23,12 @@
#include <android-base/unique_fd.h>
#include <fs_mgr.h>
#include <fstab/fstab.h>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <liblp/builder.h>
#include "images.h"
+#include "mock_property_fetcher.h"
#include "reader.h"
#include "test_partition_opener.h"
#include "utility.h"
@@ -34,6 +36,8 @@
using namespace std;
using namespace android::fs_mgr;
+using ::testing::_;
+using ::testing::Return;
using unique_fd = android::base::unique_fd;
// Our tests assume a 128KiB disk with two 512 byte metadata slots.
@@ -664,7 +668,8 @@
}
TEST(liblp, UpdateRetrofit) {
- MetadataBuilder::OverrideRetrofitDynamicParititonsForTesting(true);
+ ON_CALL(*GetMockedInstance(), GetBoolProperty("ro.boot.dynamic_partitions_retrofit", _))
+ .WillByDefault(Return(true));
unique_ptr<MetadataBuilder> builder = CreateDefaultBuilder();
ASSERT_NE(builder, nullptr);
@@ -695,7 +700,8 @@
}
TEST(liblp, UpdateNonRetrofit) {
- MetadataBuilder::OverrideRetrofitDynamicParititonsForTesting(false);
+ ON_CALL(*GetMockedInstance(), GetBoolProperty("ro.boot.dynamic_partitions_retrofit", _))
+ .WillByDefault(Return(false));
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
diff --git a/fs_mgr/liblp/mock_property_fetcher.h b/fs_mgr/liblp/mock_property_fetcher.h
new file mode 100644
index 0000000..eb91de2
--- /dev/null
+++ b/fs_mgr/liblp/mock_property_fetcher.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include <liblp/property_fetcher.h>
+
+namespace android {
+namespace fs_mgr {
+
+class MockPropertyFetcher : public IPropertyFetcher {
+ public:
+ MOCK_METHOD2(GetProperty, std::string(const std::string&, const std::string&));
+ MOCK_METHOD2(GetBoolProperty, bool(const std::string&, bool));
+
+ // By default, return default_value for all functions.
+ MockPropertyFetcher() {
+ using ::testing::_;
+ using ::testing::Invoke;
+ ON_CALL(*this, GetProperty(_, _)).WillByDefault(Invoke([](const auto&, const auto& def) {
+ return def;
+ }));
+ ON_CALL(*this, GetBoolProperty(_, _)).WillByDefault(Invoke([](const auto&, auto def) {
+ return def;
+ }));
+ }
+};
+
+} // namespace fs_mgr
+} // namespace android
+
+android::fs_mgr::MockPropertyFetcher* GetMockedInstance();
diff --git a/fs_mgr/liblp/property_fetcher.cpp b/fs_mgr/liblp/property_fetcher.cpp
new file mode 100644
index 0000000..038ef4d
--- /dev/null
+++ b/fs_mgr/liblp/property_fetcher.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 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 "liblp/property_fetcher.h"
+
+#include <memory>
+
+#include <android-base/properties.h>
+
+namespace android {
+namespace fs_mgr {
+
+std::string PropertyFetcher::GetProperty(const std::string& key, const std::string& default_value) {
+ return android::base::GetProperty(key, default_value);
+}
+
+bool PropertyFetcher::GetBoolProperty(const std::string& key, bool default_value) {
+ return android::base::GetBoolProperty(key, default_value);
+}
+
+static std::unique_ptr<IPropertyFetcher>* GetInstanceAllocation() {
+ static std::unique_ptr<IPropertyFetcher> instance = std::make_unique<PropertyFetcher>();
+ return &instance;
+}
+
+IPropertyFetcher* IPropertyFetcher::GetInstance() {
+ return GetInstanceAllocation()->get();
+}
+
+void IPropertyFetcher::OverrideForTesting(std::unique_ptr<IPropertyFetcher>&& fetcher) {
+ GetInstanceAllocation()->swap(fetcher);
+ fetcher.reset();
+}
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index ce979cf..062e00b 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -170,9 +170,8 @@
bool MapSnapshot(LockedFile* lock, const std::string& name, const std::string& base_device,
const std::chrono::milliseconds& timeout_ms, std::string* dev_path);
- // Remove the backing copy-on-write image for the named snapshot. If the
- // device is still mapped, this will attempt an Unmap, and fail if the
- // unmap fails.
+ // Remove the backing copy-on-write image for the named snapshot. The
+ // caller is responsible for ensuring that the snapshot is unmapped.
bool DeleteSnapshot(LockedFile* lock, const std::string& name);
// Unmap a snapshot device previously mapped with MapSnapshotDevice().
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index c982dd1..ef56179 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -300,11 +300,6 @@
CHECK(lock);
if (!EnsureImageManager()) return false;
- if (!UnmapSnapshot(lock, name)) {
- LOG(ERROR) << "Snapshot could not be unmapped for deletion: " << name;
- return false;
- }
-
// Take the snapshot's lock after Unmap, since it will also try to lock.
auto status_file = OpenSnapshotStatusFile(name, O_RDONLY, LOCK_EX);
if (!status_file) return false;
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 1b3289b..9cc9bd7 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -104,7 +104,7 @@
ASSERT_EQ(snapshots.size(), 1);
ASSERT_EQ(snapshots[0], "test-snapshot");
- // Scope so delete can re-acquire the status file lock.
+ // Scope so delete can re-acquire the snapshot file lock.
{
auto file = sm->OpenSnapshotStatusFile("test-snapshot", O_RDONLY, LOCK_SH);
ASSERT_NE(file, nullptr);
@@ -116,6 +116,7 @@
ASSERT_EQ(status.snapshot_size, kDeviceSize);
}
+ ASSERT_TRUE(sm->UnmapSnapshot(lock_.get(), "test-snapshot"));
ASSERT_TRUE(sm->DeleteSnapshot(lock_.get(), "test-snapshot"));
}
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 319a73a..5144fc6 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -68,7 +68,6 @@
"record_stream.cpp",
"sockets.cpp",
"strdup16to8.cpp",
- "strdup8to16.cpp",
"strlcpy.c",
"threads.cpp",
],
diff --git a/libcutils/include/cutils/jstring.h b/libcutils/include/cutils/jstring.h
index a342608..6ede786 100644
--- a/libcutils/include/cutils/jstring.h
+++ b/libcutils/include/cutils/jstring.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef __CUTILS_STRING16_H
-#define __CUTILS_STRING16_H
+#pragma once
#include <stdint.h>
#include <stddef.h>
@@ -33,14 +32,6 @@
extern size_t strnlen16to8 (const char16_t* s, size_t n);
extern char * strncpy16to8 (char *dest, const char16_t*s, size_t n);
-extern char16_t * strdup8to16 (const char* s, size_t *out_len);
-extern size_t strlen8to16 (const char* utf8Str);
-extern char16_t * strcpy8to16 (char16_t *dest, const char*s, size_t *out_len);
-extern char16_t * strcpylen8to16 (char16_t *dest, const char*s, int length,
- size_t *out_len);
-
#ifdef __cplusplus
}
#endif
-
-#endif /* __CUTILS_STRING16_H */
diff --git a/libcutils/strdup8to16.cpp b/libcutils/strdup8to16.cpp
deleted file mode 100644
index d1e51b9..0000000
--- a/libcutils/strdup8to16.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-/* libs/cutils/strdup8to16.c
-**
-** Copyright 2006, 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 <cutils/jstring.h>
-
-#include <assert.h>
-#include <limits.h>
-#include <stdlib.h>
-
-/* See http://www.unicode.org/reports/tr22/ for discussion
- * on invalid sequences
- */
-
-#define UTF16_REPLACEMENT_CHAR 0xfffd
-
-/* Clever trick from Dianne that returns 1-4 depending on leading bit sequence*/
-#define UTF8_SEQ_LENGTH(ch) (((0xe5000000 >> (((ch) >> 3) & 0x1e)) & 3) + 1)
-
-/* note: macro expands to multiple lines */
-#define UTF8_SHIFT_AND_MASK(unicode, byte) \
- (unicode)<<=6; (unicode) |= (0x3f & (byte));
-
-#define UNICODE_UPPER_LIMIT 0x10fffd
-
-/**
- * out_len is an out parameter (which may not be null) containing the
- * length of the UTF-16 string (which may contain embedded \0's)
- */
-
-extern char16_t * strdup8to16 (const char* s, size_t *out_len)
-{
- char16_t *ret;
- size_t len;
-
- if (s == NULL) return NULL;
-
- len = strlen8to16(s);
-
- // fail on overflow
- if (len && SIZE_MAX/len < sizeof(char16_t))
- return NULL;
-
- // no plus-one here. UTF-16 strings are not null terminated
- ret = (char16_t *) malloc (sizeof(char16_t) * len);
-
- return strcpy8to16 (ret, s, out_len);
-}
-
-/**
- * Like "strlen", but for strings encoded with Java's modified UTF-8.
- *
- * The value returned is the number of UTF-16 characters required
- * to represent this string.
- */
-extern size_t strlen8to16 (const char* utf8Str)
-{
- size_t len = 0;
- int ic;
- int expected = 0;
-
- while ((ic = *utf8Str++) != '\0') {
- /* bytes that start 0? or 11 are lead bytes and count as characters.*/
- /* bytes that start 10 are extention bytes and are not counted */
-
- if ((ic & 0xc0) == 0x80) {
- /* count the 0x80 extention bytes. if we have more than
- * expected, then start counting them because strcpy8to16
- * will insert UTF16_REPLACEMENT_CHAR's
- */
- expected--;
- if (expected < 0) {
- len++;
- }
- } else {
- len++;
- expected = UTF8_SEQ_LENGTH(ic) - 1;
-
- /* this will result in a surrogate pair */
- if (expected == 3) {
- len++;
- }
- }
- }
-
- return len;
-}
-
-
-
-/*
- * Retrieve the next UTF-32 character from a UTF-8 string.
- *
- * Stops at inner \0's
- *
- * Returns UTF16_REPLACEMENT_CHAR if an invalid sequence is encountered
- *
- * Advances "*pUtf8Ptr" to the start of the next character.
- */
-static inline uint32_t getUtf32FromUtf8(const char** pUtf8Ptr)
-{
- uint32_t ret;
- int seq_len;
- int i;
-
- /* Mask for leader byte for lengths 1, 2, 3, and 4 respectively*/
- static const unsigned char leaderMask[4] = {0xff, 0x1f, 0x0f, 0x07};
-
- /* Bytes that start with bits "10" are not leading characters. */
- if (((**pUtf8Ptr) & 0xc0) == 0x80) {
- (*pUtf8Ptr)++;
- return UTF16_REPLACEMENT_CHAR;
- }
-
- /* note we tolerate invalid leader 11111xxx here */
- seq_len = UTF8_SEQ_LENGTH(**pUtf8Ptr);
-
- ret = (**pUtf8Ptr) & leaderMask [seq_len - 1];
-
- if (**pUtf8Ptr == '\0') return ret;
-
- (*pUtf8Ptr)++;
- for (i = 1; i < seq_len ; i++, (*pUtf8Ptr)++) {
- if ((**pUtf8Ptr) == '\0') return UTF16_REPLACEMENT_CHAR;
- if (((**pUtf8Ptr) & 0xc0) != 0x80) return UTF16_REPLACEMENT_CHAR;
-
- UTF8_SHIFT_AND_MASK(ret, **pUtf8Ptr);
- }
-
- return ret;
-}
-
-
-/**
- * out_len is an out parameter (which may not be null) containing the
- * length of the UTF-16 string (which may contain embedded \0's)
- */
-
-extern char16_t * strcpy8to16 (char16_t *utf16Str, const char*utf8Str,
- size_t *out_len)
-{
- char16_t *dest = utf16Str;
-
- while (*utf8Str != '\0') {
- uint32_t ret;
-
- ret = getUtf32FromUtf8(&utf8Str);
-
- if (ret <= 0xffff) {
- *dest++ = (char16_t) ret;
- } else if (ret <= UNICODE_UPPER_LIMIT) {
- /* Create surrogate pairs */
- /* See http://en.wikipedia.org/wiki/UTF-16/UCS-2#Method_for_code_points_in_Plane_1.2C_Plane_2 */
-
- *dest++ = 0xd800 | ((ret - 0x10000) >> 10);
- *dest++ = 0xdc00 | ((ret - 0x10000) & 0x3ff);
- } else {
- *dest++ = UTF16_REPLACEMENT_CHAR;
- }
- }
-
- *out_len = dest - utf16Str;
-
- return utf16Str;
-}
-
-/**
- * length is the number of characters in the UTF-8 string.
- * out_len is an out parameter (which may not be null) containing the
- * length of the UTF-16 string (which may contain embedded \0's)
- */
-
-extern char16_t * strcpylen8to16 (char16_t *utf16Str, const char*utf8Str,
- int length, size_t *out_len)
-{
- /* TODO: Share more of this code with the method above. Only 2 lines changed. */
-
- char16_t *dest = utf16Str;
-
- const char *end = utf8Str + length; /* This line */
- while (utf8Str < end) { /* and this line changed. */
- uint32_t ret;
-
- ret = getUtf32FromUtf8(&utf8Str);
-
- if (ret <= 0xffff) {
- *dest++ = (char16_t) ret;
- } else if (ret <= UNICODE_UPPER_LIMIT) {
- /* Create surrogate pairs */
- /* See http://en.wikipedia.org/wiki/UTF-16/UCS-2#Method_for_code_points_in_Plane_1.2C_Plane_2 */
-
- *dest++ = 0xd800 | ((ret - 0x10000) >> 10);
- *dest++ = 0xdc00 | ((ret - 0x10000) & 0x3ff);
- } else {
- *dest++ = UTF16_REPLACEMENT_CHAR;
- }
- }
-
- *out_len = dest - utf16Str;
-
- return utf16Str;
-}
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 76d6f7e..4559050 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -230,7 +230,7 @@
# A symlink can't overwrite a directory and the /system/usr/icu directory once
# existed so the required structure must be created whatever we find.
LOCAL_POST_INSTALL_CMD = mkdir -p $(TARGET_OUT)/usr && rm -rf $(TARGET_OUT)/usr/icu
-LOCAL_POST_INSTALL_CMD += && ln -sf /apex/com.android.runtime/etc/icu $(TARGET_OUT)/usr/icu
+LOCAL_POST_INSTALL_CMD += && ln -sf /apex/com.android.i18n/etc/icu $(TARGET_OUT)/usr/icu
# TODO(b/124106384): Clean up compat symlinks for ART binaries.
ART_BINARIES := \
diff --git a/rootdir/init.environ.rc.in b/rootdir/init.environ.rc.in
index 455c9a8..93b7f43 100644
--- a/rootdir/init.environ.rc.in
+++ b/rootdir/init.environ.rc.in
@@ -6,6 +6,7 @@
export ANDROID_DATA /data
export ANDROID_STORAGE /storage
export ANDROID_RUNTIME_ROOT /apex/com.android.runtime
+ export ANDROID_I18N_ROOT /apex/com.android.i18n
export ANDROID_TZDATA_ROOT /apex/com.android.tzdata
export EXTERNAL_STORAGE /sdcard
export ASEC_MOUNTPOINT /mnt/asec