It turns the version code into almost a 64-bit integer, with the new major part being the upper 32 bits. The only tricky part about this is the backup manager, since it stored 32-bit version codes in its backup data sets. This is dealt with by, when the major version code is not 0, writing MIN_INT as the version code and following that by the full long version code, which we can detect when reading. Note that this makes backup sets containing apps with major version codes incompatible with older versions of the platform. Bug: 64459786 Test: Added in Change-Id: Iab8a682b62103babd6c16a56b8dc1e97d7078658 Change-Id: Ibfffe235bbfcf358b3741abd3f7197fdb063d3f3
222 lines
6.7 KiB
C++
222 lines
6.7 KiB
C++
// Copyright (C) 2017 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 "packages/UidMap.h"
|
|
#include "StatsLogProcessor.h"
|
|
#include "config/ConfigKey.h"
|
|
#include "guardrail/StatsdStats.h"
|
|
#include "logd/LogEvent.h"
|
|
#include "statslog.h"
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
using namespace android;
|
|
|
|
namespace android {
|
|
namespace os {
|
|
namespace statsd {
|
|
|
|
#ifdef __ANDROID__
|
|
const string kApp1 = "app1.sharing.1";
|
|
const string kApp2 = "app2.sharing.1";
|
|
|
|
TEST(UidMapTest, TestIsolatedUID) {
|
|
sp<UidMap> m = new UidMap();
|
|
sp<AnomalyMonitor> anomalyMonitor;
|
|
// Construct the processor with a dummy sendBroadcast function that does nothing.
|
|
StatsLogProcessor p(m, anomalyMonitor, [](const ConfigKey& key) {});
|
|
LogEvent addEvent(android::util::ISOLATED_UID_CHANGED, 1);
|
|
addEvent.write(100); // parent UID
|
|
addEvent.write(101); // isolated UID
|
|
addEvent.write(1); // Indicates creation.
|
|
addEvent.init();
|
|
|
|
EXPECT_EQ(101, m->getParentUidOrSelf(101));
|
|
|
|
p.OnLogEvent(addEvent);
|
|
EXPECT_EQ(100, m->getParentUidOrSelf(101));
|
|
|
|
LogEvent removeEvent(android::util::ISOLATED_UID_CHANGED, 1);
|
|
removeEvent.write(100); // parent UID
|
|
removeEvent.write(101); // isolated UID
|
|
removeEvent.write(0); // Indicates removal.
|
|
removeEvent.init();
|
|
p.OnLogEvent(removeEvent);
|
|
EXPECT_EQ(101, m->getParentUidOrSelf(101));
|
|
}
|
|
|
|
TEST(UidMapTest, TestMatching) {
|
|
UidMap m;
|
|
vector<int32_t> uids;
|
|
vector<int64_t> versions;
|
|
vector<String16> apps;
|
|
|
|
uids.push_back(1000);
|
|
uids.push_back(1000);
|
|
apps.push_back(String16(kApp1.c_str()));
|
|
apps.push_back(String16(kApp2.c_str()));
|
|
versions.push_back(4);
|
|
versions.push_back(5);
|
|
m.updateMap(uids, versions, apps);
|
|
EXPECT_TRUE(m.hasApp(1000, kApp1));
|
|
EXPECT_TRUE(m.hasApp(1000, kApp2));
|
|
EXPECT_FALSE(m.hasApp(1000, "not.app"));
|
|
}
|
|
|
|
TEST(UidMapTest, TestAddAndRemove) {
|
|
UidMap m;
|
|
vector<int32_t> uids;
|
|
vector<int64_t> versions;
|
|
vector<String16> apps;
|
|
|
|
uids.push_back(1000);
|
|
uids.push_back(1000);
|
|
apps.push_back(String16(kApp1.c_str()));
|
|
apps.push_back(String16(kApp2.c_str()));
|
|
versions.push_back(4);
|
|
versions.push_back(5);
|
|
m.updateMap(uids, versions, apps);
|
|
|
|
m.updateApp(String16(kApp1.c_str()), 1000, 40);
|
|
EXPECT_EQ(40, m.getAppVersion(1000, kApp1));
|
|
|
|
m.removeApp(String16(kApp1.c_str()), 1000);
|
|
EXPECT_FALSE(m.hasApp(1000, kApp1));
|
|
EXPECT_TRUE(m.hasApp(1000, kApp2));
|
|
}
|
|
|
|
TEST(UidMapTest, TestClearingOutput) {
|
|
UidMap m;
|
|
|
|
ConfigKey config1(1, "config1");
|
|
ConfigKey config2(1, "config2");
|
|
|
|
m.OnConfigUpdated(config1);
|
|
|
|
vector<int32_t> uids;
|
|
vector<int64_t> versions;
|
|
vector<String16> apps;
|
|
uids.push_back(1000);
|
|
uids.push_back(1000);
|
|
apps.push_back(String16(kApp1.c_str()));
|
|
apps.push_back(String16(kApp2.c_str()));
|
|
versions.push_back(4);
|
|
versions.push_back(5);
|
|
m.updateMap(1, uids, versions, apps);
|
|
EXPECT_EQ(1, m.mOutput.snapshots_size());
|
|
|
|
UidMapping results = m.getOutput(2, config1);
|
|
EXPECT_EQ(1, results.snapshots_size());
|
|
|
|
// It should be cleared now
|
|
EXPECT_EQ(0, m.mOutput.snapshots_size());
|
|
results = m.getOutput(3, config1);
|
|
EXPECT_EQ(0, results.snapshots_size());
|
|
|
|
// Now add another configuration.
|
|
m.OnConfigUpdated(config2);
|
|
m.updateApp(5, String16(kApp1.c_str()), 1000, 40);
|
|
EXPECT_EQ(1, m.mOutput.changes_size());
|
|
results = m.getOutput(6, config1);
|
|
EXPECT_EQ(0, results.snapshots_size());
|
|
EXPECT_EQ(1, results.changes_size());
|
|
EXPECT_EQ(1, m.mOutput.changes_size());
|
|
|
|
// Add another delta update.
|
|
m.updateApp(7, String16(kApp2.c_str()), 1001, 41);
|
|
EXPECT_EQ(2, m.mOutput.changes_size());
|
|
|
|
// We still can't remove anything.
|
|
results = m.getOutput(8, config1);
|
|
EXPECT_EQ(0, results.snapshots_size());
|
|
EXPECT_EQ(2, results.changes_size());
|
|
EXPECT_EQ(2, m.mOutput.changes_size());
|
|
|
|
results = m.getOutput(9, config2);
|
|
EXPECT_EQ(0, results.snapshots_size());
|
|
EXPECT_EQ(2, results.changes_size());
|
|
// At this point both should be cleared.
|
|
EXPECT_EQ(0, m.mOutput.snapshots_size());
|
|
EXPECT_EQ(0, m.mOutput.changes_size());
|
|
}
|
|
|
|
TEST(UidMapTest, TestMemoryComputed) {
|
|
UidMap m;
|
|
|
|
ConfigKey config1(1, "config1");
|
|
m.OnConfigUpdated(config1);
|
|
|
|
size_t startBytes = m.mBytesUsed;
|
|
vector<int32_t> uids;
|
|
vector<int64_t> versions;
|
|
vector<String16> apps;
|
|
uids.push_back(1000);
|
|
apps.push_back(String16(kApp1.c_str()));
|
|
versions.push_back(1);
|
|
m.updateMap(1, uids, versions, apps);
|
|
size_t snapshot_bytes = m.mBytesUsed;
|
|
EXPECT_TRUE(snapshot_bytes > startBytes);
|
|
|
|
m.updateApp(3, String16(kApp1.c_str()), 1000, 40);
|
|
EXPECT_TRUE(m.mBytesUsed > snapshot_bytes);
|
|
size_t bytesWithSnapshotChange = m.mBytesUsed;
|
|
|
|
m.getOutput(2, config1);
|
|
EXPECT_TRUE(m.mBytesUsed < bytesWithSnapshotChange);
|
|
size_t prevBytes = m.mBytesUsed;
|
|
|
|
m.getOutput(4, config1);
|
|
EXPECT_TRUE(m.mBytesUsed < prevBytes);
|
|
}
|
|
|
|
TEST(UidMapTest, TestMemoryGuardrail) {
|
|
UidMap m;
|
|
string buf;
|
|
|
|
ConfigKey config1(1, "config1");
|
|
m.OnConfigUpdated(config1);
|
|
|
|
size_t startBytes = m.mBytesUsed;
|
|
vector<int32_t> uids;
|
|
vector<int64_t> versions;
|
|
vector<String16> apps;
|
|
for (int i = 0; i < 100; i++) {
|
|
uids.push_back(1);
|
|
buf = "EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY." + to_string(i);
|
|
apps.push_back(String16(buf.c_str()));
|
|
versions.push_back(1);
|
|
}
|
|
m.updateMap(1, uids, versions, apps);
|
|
EXPECT_EQ(1, m.mOutput.snapshots_size());
|
|
|
|
m.updateApp(3, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 2);
|
|
EXPECT_EQ(1, m.mOutput.snapshots_size());
|
|
EXPECT_EQ(1, m.mOutput.changes_size());
|
|
|
|
// Now force deletion by limiting the memory to hold one delta change.
|
|
m.maxBytesOverride = 80; // Since the app string alone requires >45 characters.
|
|
m.updateApp(5, String16("EXTREMELY_LONG_STRING_FOR_APP_TO_WASTE_MEMORY.0"), 1000, 4);
|
|
EXPECT_EQ(0, m.mOutput.snapshots_size());
|
|
EXPECT_EQ(1, m.mOutput.changes_size());
|
|
}
|
|
#else
|
|
GTEST_LOG_(INFO) << "This test does nothing.\n";
|
|
#endif
|
|
|
|
} // namespace statsd
|
|
} // namespace os
|
|
} // namespace android
|