Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1388a58d authored by Jason Macnak's avatar Jason Macnak Committed by Android (Google) Code Review
Browse files

Merge "Make display unique id stable across x86 and x86_64 builds"

parents 17b120da 4afe8576
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -146,6 +146,7 @@ filegroup {
        "DisplayHardware/ComposerHal.cpp",
        "DisplayHardware/DisplayIdentification.cpp",
        "DisplayHardware/FramebufferSurface.cpp",
        "DisplayHardware/Hash.cpp",
        "DisplayHardware/HWC2.cpp",
        "DisplayHardware/HWComposer.cpp",
        "DisplayHardware/PowerAdvisor.cpp",
+4 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <log/log.h>

#include "DisplayIdentification.h"
#include "Hash.h"

namespace android {
namespace {
@@ -262,8 +263,9 @@ std::optional<Edid> parseEdid(const DisplayIdentificationData& edid) {
    }

    // Hash model string instead of using product code or (integer) serial number, since the latter
    // have been observed to change on some displays with multiple inputs.
    const auto modelHash = static_cast<uint32_t>(std::hash<std::string_view>()(modelString));
    // have been observed to change on some displays with multiple inputs. Use a stable hash instead
    // of std::hash which is only required to be same within a single execution of a program.
    const uint32_t modelHash = static_cast<uint32_t>(cityHash64Len0To16(modelString));

    // Parse extension blocks.
    std::optional<Cea861ExtensionBlock> cea861Block;
+93 −0
Original line number Diff line number Diff line
/*
 * Copyright 2021 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.
 */

#undef LOG_TAG
#define LOG_TAG "DisplayIdentification"

#include <cstring>
#include <type_traits>

#include <log/log.h>

#include "Hash.h"

namespace android {
namespace {

template <class T>
inline T load(const void* p) {
    static_assert(std::is_integral<T>::value, "T must be integral");

    T r;
    std::memcpy(&r, p, sizeof(r));
    return r;
}

uint64_t rotateByAtLeast1(uint64_t val, uint8_t shift) {
    return (val >> shift) | (val << (64 - shift));
}

uint64_t shiftMix(uint64_t val) {
    return val ^ (val >> 47);
}

uint64_t hash64Len16(uint64_t u, uint64_t v) {
    constexpr uint64_t kMul = 0x9ddfea08eb382d69;
    uint64_t a = (u ^ v) * kMul;
    a ^= (a >> 47);
    uint64_t b = (v ^ a) * kMul;
    b ^= (b >> 47);
    b *= kMul;
    return b;
}

uint64_t hash64Len0To16(const char* s, uint64_t len) {
    constexpr uint64_t k2 = 0x9ae16a3b2f90404f;
    constexpr uint64_t k3 = 0xc949d7c7509e6557;

    if (len > 8) {
        const uint64_t a = load<uint64_t>(s);
        const uint64_t b = load<uint64_t>(s + len - 8);
        return hash64Len16(a, rotateByAtLeast1(b + len, static_cast<uint8_t>(len))) ^ b;
    }
    if (len >= 4) {
        const uint32_t a = load<uint32_t>(s);
        const uint32_t b = load<uint32_t>(s + len - 4);
        return hash64Len16(len + (a << 3), b);
    }
    if (len > 0) {
        const unsigned char a = static_cast<unsigned char>(s[0]);
        const unsigned char b = static_cast<unsigned char>(s[len >> 1]);
        const unsigned char c = static_cast<unsigned char>(s[len - 1]);
        const uint32_t y = static_cast<uint32_t>(a) + (static_cast<uint32_t>(b) << 8);
        const uint32_t z = static_cast<uint32_t>(len) + (static_cast<uint32_t>(c) << 2);
        return shiftMix(y * k2 ^ z * k3) * k2;
    }
    return k2;
}

} // namespace

uint64_t cityHash64Len0To16(std::string_view sv) {
    auto len = sv.length();
    if (len > 16) {
        ALOGE("%s called with length %zu. Only hashing the first 16 chars", __FUNCTION__, len);
        len = 16;
    }
    return hash64Len0To16(sv.data(), len);
}

} // namespace android
 No newline at end of file
+27 −0
Original line number Diff line number Diff line
/*
 * Copyright 2021 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 <cstdint>
#include <string_view>

namespace android {

// CityHash64 implementation that only hashes at most the first 16 characters of the given string.
uint64_t cityHash64Len0To16(std::string_view sv);

} // namespace android
 No newline at end of file
+5 −4
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <gtest/gtest.h>

#include "DisplayHardware/DisplayIdentification.h"
#include "DisplayHardware/Hash.h"

using ::testing::ElementsAre;

@@ -134,7 +135,7 @@ DisplayIdentificationData asDisplayIdentificationData(const unsigned char (&byte
}

uint32_t hash(const char* str) {
    return static_cast<uint32_t>(std::hash<std::string_view>()(str));
    return static_cast<uint32_t>(cityHash64Len0To16(str));
}

} // namespace
@@ -309,9 +310,9 @@ TEST(DisplayIdentificationTest, parseDisplayIdentificationData) {
    ASSERT_TRUE(tertiaryInfo);

    // Display IDs should be unique.
    EXPECT_NE(primaryInfo->id, secondaryInfo->id);
    EXPECT_NE(primaryInfo->id, tertiaryInfo->id);
    EXPECT_NE(secondaryInfo->id, tertiaryInfo->id);
    EXPECT_EQ(4633257497453176576, primaryInfo->id.value);
    EXPECT_EQ(4621520285560261121, secondaryInfo->id.value);
    EXPECT_EQ(4633127902230889474, tertiaryInfo->id.value);
}

TEST(DisplayIdentificationTest, deviceProductInfo) {