summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt3
-rw-r--r--api/system-current.txt1
-rw-r--r--api/test-current.txt18
-rw-r--r--cmds/idmap2/Android.bp2
-rw-r--r--cmds/idmap2/idmap2/Create.cpp31
-rw-r--r--cmds/idmap2/idmap2/Scan.cpp107
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.cpp22
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.h7
-rw-r--r--cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl13
-rw-r--r--cmds/idmap2/include/idmap2/CommandLineOptions.h3
-rw-r--r--cmds/idmap2/include/idmap2/Idmap.h11
-rw-r--r--cmds/idmap2/include/idmap2/Policies.h41
-rw-r--r--cmds/idmap2/libidmap2/CommandLineOptions.cpp23
-rw-r--r--cmds/idmap2/libidmap2/Idmap.cpp31
-rw-r--r--cmds/idmap2/libidmap2/Policies.cpp57
-rw-r--r--cmds/idmap2/tests/BinaryStreamVisitorTests.cpp42
-rw-r--r--cmds/idmap2/tests/CommandLineOptionsTests.cpp56
-rw-r--r--cmds/idmap2/tests/FileUtilsTests.cpp14
-rw-r--r--cmds/idmap2/tests/Idmap2BinaryTests.cpp32
-rw-r--r--cmds/idmap2/tests/IdmapTests.cpp129
-rw-r--r--cmds/idmap2/tests/PoliciesTests.cpp70
-rw-r--r--cmds/idmap2/tests/PrettyPrintVisitorTests.cpp5
-rw-r--r--cmds/idmap2/tests/RawPrintVisitorTests.cpp5
-rw-r--r--cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml21
-rw-r--r--cmds/idmap2/tests/data/system-overlay-invalid/build26
-rw-r--r--cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml29
-rw-r--r--cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apkbin0 -> 1427 bytes
-rw-r--r--cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml21
-rw-r--r--cmds/idmap2/tests/data/system-overlay/build26
-rw-r--r--cmds/idmap2/tests/data/system-overlay/res/values/values.xml22
-rw-r--r--cmds/idmap2/tests/data/system-overlay/system-overlay.apkbin0 -> 1283 bytes
-rw-r--r--cmds/idmap2/tests/data/target/res/values/overlayable.xml48
-rw-r--r--cmds/idmap2/tests/data/target/res/values/values.xml8
-rw-r--r--cmds/idmap2/tests/data/target/target.apkbin2173 -> 3669 bytes
-rw-r--r--cmds/statsd/src/atoms.proto21
-rw-r--r--config/hiddenapi-greylist.txt24
-rw-r--r--core/java/android/content/pm/ShortcutInfo.java114
-rw-r--r--core/java/android/os/VintfObject.java37
-rw-r--r--core/java/android/os/VintfRuntimeInfo.java31
-rw-r--r--core/java/android/provider/DeviceConfig.java7
-rw-r--r--core/java/android/view/LayoutInflater.java37
-rw-r--r--core/java/android/view/SurfaceControl.java38
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java27
-rw-r--r--core/jni/android_view_SurfaceControl.cpp23
-rw-r--r--core/res/res/values/config.xml5
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h4
-rw-r--r--libs/androidfw/tests/LoadedArsc_test.cpp1
-rw-r--r--libs/androidfw/tests/data/overlayable/overlayable.apkbin5523 -> 3443 bytes
-rw-r--r--libs/androidfw/tests/data/overlayable/res/values/overlayable.xml4
-rw-r--r--media/jni/android_media_MediaCodec.cpp2
-rw-r--r--packages/SystemUI/res-keyguard/layout/type_clock.xml55
-rw-r--r--packages/SystemUI/res-keyguard/values/colors.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values/strings.xml83
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java106
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java110
-rw-r--r--services/core/java/com/android/server/om/IdmapManager.java84
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerServiceImpl.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java32
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java34
-rw-r--r--telephony/java/android/telephony/PhoneStateListener.java8
-rw-r--r--telephony/java/android/telephony/ims/ImsMmTelManager.java55
-rw-r--r--telephony/java/android/telephony/ims/ProvisioningManager.java25
-rw-r--r--tests/ActivityViewTest/AndroidManifest.xml5
-rw-r--r--tests/ActivityViewTest/res/layout/activity_view_main_activity.xml6
-rw-r--r--tests/ActivityViewTest/res/layout/activity_view_visibility_activity.xml46
-rw-r--r--tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java3
-rw-r--r--tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java3
-rw-r--r--tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewVisibilityActivity.java75
-rw-r--r--tools/aapt2/ResourceParser.cpp2
-rw-r--r--tools/aapt2/ResourceParser_test.cpp17
-rw-r--r--tools/aapt2/ResourceTable.h3
-rw-r--r--tools/aapt2/ResourceTable_test.cpp4
-rw-r--r--tools/aapt2/Resources.proto1
-rw-r--r--tools/aapt2/format/binary/BinaryResourceParser.cpp4
-rw-r--r--tools/aapt2/format/binary/TableFlattener.cpp3
-rw-r--r--tools/aapt2/format/binary/TableFlattener_test.cpp16
-rw-r--r--tools/aapt2/format/proto/ProtoDeserialize.cpp3
-rw-r--r--tools/aapt2/format/proto/ProtoSerialize.cpp3
-rw-r--r--tools/aapt2/format/proto/ProtoSerialize_test.cpp4
-rw-r--r--tools/aapt2/link/TableMerger_test.cpp4
85 files changed, 1893 insertions, 232 deletions
diff --git a/api/current.txt b/api/current.txt
index b5b47b0d5c78..c027dd733a67 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11950,6 +11950,9 @@ package android.content.pm {
method public android.content.pm.ShortcutInfo.Builder setIntent(android.content.Intent);
method public android.content.pm.ShortcutInfo.Builder setIntents(android.content.Intent[]);
method public android.content.pm.ShortcutInfo.Builder setLongLabel(java.lang.CharSequence);
+ method public android.content.pm.ShortcutInfo.Builder setLongLived();
+ method public android.content.pm.ShortcutInfo.Builder setPerson(android.app.Person);
+ method public android.content.pm.ShortcutInfo.Builder setPersons(android.app.Person[]);
method public android.content.pm.ShortcutInfo.Builder setRank(int);
method public android.content.pm.ShortcutInfo.Builder setShortLabel(java.lang.CharSequence);
}
diff --git a/api/system-current.txt b/api/system-current.txt
index eaca6ab96f0e..dc5d266ac9bb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5092,6 +5092,7 @@ package android.provider {
method public static void removeOnPropertyChangedListener(android.provider.DeviceConfig.OnPropertyChangedListener);
method public static void resetToDefaults(int, java.lang.String);
method public static boolean setProperty(java.lang.String, java.lang.String, java.lang.String, boolean);
+ field public static final java.lang.String NAMESPACE_GAME_DRIVER = "game_driver";
field public static final java.lang.String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot";
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 5fcbb5e375e7..e0e0f3506ad4 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1118,6 +1118,24 @@ package android.os {
field public static final android.os.Parcelable.Creator<android.os.VibrationEffect.Waveform> CREATOR;
}
+ public class VintfObject {
+ method public static java.lang.String[] getHalNamesAndVersions();
+ method public static java.lang.String getSepolicyVersion();
+ method public static java.lang.Long getTargetFrameworkCompatibilityMatrixVersion();
+ method public static java.util.Map<java.lang.String, java.lang.String[]> getVndkSnapshots();
+ method public static java.lang.String[] report();
+ }
+
+ public class VintfRuntimeInfo {
+ method public static java.lang.String getCpuInfo();
+ method public static java.lang.String getHardwareId();
+ method public static java.lang.String getKernelVersion();
+ method public static java.lang.String getNodeName();
+ method public static java.lang.String getOsName();
+ method public static java.lang.String getOsRelease();
+ method public static java.lang.String getOsVersion();
+ }
+
public class WorkSource implements android.os.Parcelable {
ctor public WorkSource(int);
method public boolean add(int);
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index 423bbd22fb58..803f83c0bc6f 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -39,6 +39,7 @@ cc_library {
"libidmap2/CommandLineOptions.cpp",
"libidmap2/FileUtils.cpp",
"libidmap2/Idmap.cpp",
+ "libidmap2/Policies.cpp",
"libidmap2/PrettyPrintVisitor.cpp",
"libidmap2/RawPrintVisitor.cpp",
"libidmap2/ResourceUtils.cpp",
@@ -88,6 +89,7 @@ cc_test {
"tests/Idmap2BinaryTests.cpp",
"tests/IdmapTests.cpp",
"tests/Main.cpp",
+ "tests/PoliciesTests.cpp",
"tests/PrettyPrintVisitorTests.cpp",
"tests/RawPrintVisitorTests.cpp",
"tests/ResourceUtilsTests.cpp",
diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp
index b07567331e85..c455ac0f83af 100644
--- a/cmds/idmap2/idmap2/Create.cpp
+++ b/cmds/idmap2/idmap2/Create.cpp
@@ -27,17 +27,25 @@
#include "idmap2/CommandLineOptions.h"
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
+#include "idmap2/Policies.h"
+#include "idmap2/Result.h"
using android::ApkAssets;
using android::idmap2::BinaryStreamVisitor;
using android::idmap2::CommandLineOptions;
using android::idmap2::Idmap;
+using android::idmap2::PoliciesToBitmask;
+using android::idmap2::PolicyBitmask;
+using android::idmap2::PolicyFlags;
+using android::idmap2::Result;
using android::idmap2::utils::kIdmapFilePermissionMask;
bool Create(const std::vector<std::string>& args, std::ostream& out_error) {
std::string target_apk_path;
std::string overlay_apk_path;
std::string idmap_path;
+ std::vector<std::string> policies;
+ bool ignore_overlayable;
const CommandLineOptions opts =
CommandLineOptions("idmap2 create")
@@ -47,12 +55,28 @@ bool Create(const std::vector<std::string>& args, std::ostream& out_error) {
.MandatoryOption("--overlay-apk-path",
"input: path to apk which contains the new resource values",
&overlay_apk_path)
- .MandatoryOption("--idmap-path", "output: path to where to write idmap file",
- &idmap_path);
+ .MandatoryOption("--idmap-path", "output: path to where to write idmap file", &idmap_path)
+ .OptionalOption("--policy",
+ "input: an overlayable policy this overlay fulfills "
+ "(if none or supplied, the overlay policy will default to \"public\")",
+ &policies)
+ .OptionalFlag("--ignore-overlayable", "disables overlayable and policy checks",
+ &ignore_overlayable);
if (!opts.Parse(args, out_error)) {
return false;
}
+ PolicyBitmask fulfilled_policies = 0;
+ if (auto result = PoliciesToBitmask(policies, out_error)) {
+ fulfilled_policies |= *result;
+ } else {
+ return false;
+ }
+
+ if (fulfilled_policies == 0) {
+ fulfilled_policies |= PolicyFlags::POLICY_PUBLIC;
+ }
+
const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
if (!target_apk) {
out_error << "error: failed to load apk " << target_apk_path << std::endl;
@@ -66,7 +90,8 @@ bool Create(const std::vector<std::string>& args, std::ostream& out_error) {
}
const std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, out_error);
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ fulfilled_policies, !ignore_overlayable, out_error);
if (!idmap) {
return false;
}
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index 4f88127f8af1..a269ee958497 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -21,8 +21,11 @@
#include <set>
#include <sstream>
#include <string>
+#include <utility>
#include <vector>
+#include "android-base/properties.h"
+
#include "idmap2/CommandLineOptions.h"
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
@@ -34,6 +37,10 @@
using android::idmap2::CommandLineOptions;
using android::idmap2::Idmap;
using android::idmap2::MemoryChunk;
+using android::idmap2::PoliciesToBitmask;
+using android::idmap2::PolicyBitmask;
+using android::idmap2::PolicyFlags;
+using android::idmap2::Result;
using android::idmap2::Xml;
using android::idmap2::ZipFile;
using android::idmap2::utils::FindFiles;
@@ -45,11 +52,19 @@ struct InputOverlay {
return priority < rhs.priority || (priority == rhs.priority && apk_path < rhs.apk_path);
}
- std::string apk_path; // NOLINT(misc-non-private-member-variables-in-classes)
- std::string idmap_path; // NOLINT(misc-non-private-member-variables-in-classes)
- int priority; // NOLINT(misc-non-private-member-variables-in-classes)
+ std::string apk_path; // NOLINT(misc-non-private-member-variables-in-classes)
+ std::string idmap_path; // NOLINT(misc-non-private-member-variables-in-classes)
+ int priority; // NOLINT(misc-non-private-member-variables-in-classes)
+ std::vector<std::string> policies; // NOLINT(misc-non-private-member-variables-in-classes)
+ bool ignore_overlayable; // NOLINT(misc-non-private-member-variables-in-classes)
};
+bool VendorIsQOrLater() {
+ // STOPSHIP(b/119390857): Check api version once Q sdk version is finalized
+ std::string version = android::base::GetProperty("ro.vndk.version", "Q");
+ return version == "Q" || version == "q";
+}
+
std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::string>& dirs,
bool recursive, std::ostream& out_error) {
const auto predicate = [](unsigned char type, const std::string& path) -> bool {
@@ -70,6 +85,22 @@ std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::st
return std::make_unique<std::vector<std::string>>(paths.cbegin(), paths.cend());
}
+PolicyBitmask PolicyForPath(const std::string& apk_path) {
+ static const std::vector<std::pair<std::string, PolicyBitmask>> values = {
+ {"/product/", PolicyFlags::POLICY_PRODUCT_PARTITION},
+ {"/system/", PolicyFlags::POLICY_SYSTEM_PARTITION},
+ {"/vendor/", PolicyFlags::POLICY_VENDOR_PARTITION},
+ };
+
+ for (auto const& pair : values) {
+ if (apk_path.compare(0, pair.first.size(), pair.first) == 0) {
+ return pair.second | PolicyFlags::POLICY_PUBLIC;
+ }
+ }
+
+ return PolicyFlags::POLICY_PUBLIC;
+}
+
} // namespace
bool Scan(const std::vector<std::string>& args, std::ostream& out_error) {
@@ -77,6 +108,7 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) {
std::string target_package_name;
std::string target_apk_path;
std::string output_directory;
+ std::vector<std::string> override_policies;
bool recursive = false;
const CommandLineOptions opts =
@@ -89,7 +121,12 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) {
.MandatoryOption("--target-apk-path", "path to target apk", &target_apk_path)
.MandatoryOption("--output-directory",
"directory in which to write artifacts (idmap files and overlays.list)",
- &output_directory);
+ &output_directory)
+ .OptionalOption(
+ "--override-policy",
+ "input: an overlayable policy this overlay fulfills "
+ "(if none or supplied, the overlays will not have their policies overriden",
+ &override_policies);
if (!opts.Parse(args, out_error)) {
return false;
}
@@ -144,29 +181,63 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) {
continue;
}
- // Sort the static overlays in ascending priority order
+ PolicyBitmask fulfilled_policies;
+ if (!override_policies.empty()) {
+ if (Result<PolicyBitmask> result = PoliciesToBitmask(override_policies, out_error)) {
+ fulfilled_policies = *result;
+ } else {
+ return false;
+ }
+ } else {
+ fulfilled_policies = PolicyForPath(path);
+ }
+
+ bool ignore_overlayable = false;
+ if ((fulfilled_policies & PolicyFlags::POLICY_VENDOR_PARTITION) != 0 && !VendorIsQOrLater()) {
+ // If the overlay is on a pre-Q vendor partition, do not enforce overlayable
+ // restrictions on this overlay because the pre-Q platform has no understanding of
+ // overlayable.
+ ignore_overlayable = true;
+ }
+
std::string idmap_path = Idmap::CanonicalIdmapPathFor(output_directory, path);
- InputOverlay input{path, idmap_path, priority};
+
+ // Sort the static overlays in ascending priority order
+ InputOverlay input{path, idmap_path, priority, override_policies, ignore_overlayable};
interesting_apks.insert(
std::lower_bound(interesting_apks.begin(), interesting_apks.end(), input), input);
}
std::stringstream stream;
for (const auto& overlay : interesting_apks) {
+ // Create the idmap for the overlay if it currently does not exist or if it is not up to date.
std::stringstream dev_null;
- if (!Verify(std::vector<std::string>({"--idmap-path", overlay.idmap_path}), dev_null) &&
- !Create(std::vector<std::string>({
- "--target-apk-path",
- target_apk_path,
- "--overlay-apk-path",
- overlay.apk_path,
- "--idmap-path",
- overlay.idmap_path,
- }),
- out_error)) {
- return false;
+
+ std::vector<std::string> verify_args = {"--idmap-path", overlay.idmap_path};
+ for (const std::string& policy : overlay.policies) {
+ verify_args.emplace_back("--policy");
+ verify_args.emplace_back(policy);
}
- stream << overlay.idmap_path << std::endl;
+
+ if (!Verify(std::vector<std::string>(verify_args), dev_null)) {
+ std::vector<std::string> create_args = {"--target-apk-path", target_apk_path,
+ "--overlay-apk-path", overlay.apk_path,
+ "--idmap-path", overlay.idmap_path};
+ if (overlay.ignore_overlayable) {
+ create_args.emplace_back("--ignore-overlayable");
+ }
+
+ for (const std::string& policy : overlay.policies) {
+ verify_args.emplace_back("--policy");
+ verify_args.emplace_back(policy);
+ }
+
+ if (!Create(create_args, out_error)) {
+ return false;
+ }
+ }
+
+ stream << overlay.idmap_path << std::endl;
}
std::cout << stream.str();
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index d2e46e15fc59..a3c752718ee2 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -26,12 +26,15 @@
#include <string>
#include "android-base/macros.h"
+#include "android-base/stringprintf.h"
#include "utils/String8.h"
#include "utils/Trace.h"
#include "idmap2/BinaryStreamVisitor.h"
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
+#include "idmap2/Policies.h"
+#include "idmap2/Result.h"
#include "idmap2d/Idmap2Service.h"
@@ -39,6 +42,8 @@ using android::binder::Status;
using android::idmap2::BinaryStreamVisitor;
using android::idmap2::Idmap;
using android::idmap2::IdmapHeader;
+using android::idmap2::PolicyBitmask;
+using android::idmap2::Result;
using android::idmap2::utils::kIdmapFilePermissionMask;
namespace {
@@ -54,6 +59,10 @@ Status error(const std::string& msg) {
return Status::fromExceptionCode(Status::EX_NONE, msg.c_str());
}
+PolicyBitmask ConvertAidlArgToPolicyBitmask(int32_t arg) {
+ return static_cast<PolicyBitmask>(arg);
+}
+
} // namespace
namespace android::os {
@@ -78,6 +87,8 @@ Status Idmap2Service::removeIdmap(const std::string& overlay_apk_path,
}
Status Idmap2Service::verifyIdmap(const std::string& overlay_apk_path,
+ int32_t fulfilled_policies ATTRIBUTE_UNUSED,
+ bool enforce_overlayable ATTRIBUTE_UNUSED,
int32_t user_id ATTRIBUTE_UNUSED, bool* _aidl_return) {
assert(_aidl_return);
const std::string idmap_path = Idmap::CanonicalIdmapPathFor(kIdmapCacheDir, overlay_apk_path);
@@ -86,11 +97,15 @@ Status Idmap2Service::verifyIdmap(const std::string& overlay_apk_path,
fin.close();
std::stringstream dev_null;
*_aidl_return = header && header->IsUpToDate(dev_null);
+
+ // TODO(b/119328308): Check that the set of fulfilled policies of the overlay has not changed
+
return ok();
}
Status Idmap2Service::createIdmap(const std::string& target_apk_path,
- const std::string& overlay_apk_path, int32_t user_id,
+ const std::string& overlay_apk_path, int32_t fulfilled_policies,
+ bool enforce_overlayable, int32_t user_id,
std::unique_ptr<std::string>* _aidl_return) {
assert(_aidl_return);
std::stringstream trace;
@@ -101,6 +116,8 @@ Status Idmap2Service::createIdmap(const std::string& target_apk_path,
_aidl_return->reset(nullptr);
+ const PolicyBitmask policy_bitmask = ConvertAidlArgToPolicyBitmask(fulfilled_policies);
+
const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
if (!target_apk) {
return error("failed to load apk " + target_apk_path);
@@ -113,7 +130,8 @@ Status Idmap2Service::createIdmap(const std::string& target_apk_path,
std::stringstream err;
const std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, err);
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ policy_bitmask, enforce_overlayable, err);
if (!idmap) {
return error(err.str());
}
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h
index e0bc22e9e9e6..1aab0598449b 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.h
+++ b/cmds/idmap2/idmap2d/Idmap2Service.h
@@ -39,11 +39,12 @@ class Idmap2Service : public BinderService<Idmap2Service>, public BnIdmap2 {
binder::Status removeIdmap(const std::string& overlay_apk_path, int32_t user_id,
bool* _aidl_return);
- binder::Status verifyIdmap(const std::string& overlay_apk_path, int32_t user_id,
- bool* _aidl_return);
+ binder::Status verifyIdmap(const std::string& overlay_apk_path, int32_t fulfilled_policies,
+ bool enforce_overlayable, int32_t user_id, bool* _aidl_return);
binder::Status createIdmap(const std::string& target_apk_path,
- const std::string& overlay_apk_path, int32_t user_id,
+ const std::string& overlay_apk_path, int32_t fulfilled_policies,
+ bool enforce_overlayable, int32_t user_id,
std::unique_ptr<std::string>* _aidl_return);
};
diff --git a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl
index d475417a0935..ea7274f3ea58 100644
--- a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl
+++ b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl
@@ -20,9 +20,18 @@ package android.os;
* @hide
*/
interface IIdmap2 {
+ const int POLICY_PUBLIC = 0x00000001;
+ const int POLICY_SYSTEM_PARTITION = 0x00000002;
+ const int POLICY_VENDOR_PARTITION = 0x00000004;
+ const int POLICY_PRODUCT_PARTITION = 0x00000008;
+
@utf8InCpp String getIdmapPath(@utf8InCpp String overlayApkPath, int userId);
boolean removeIdmap(@utf8InCpp String overlayApkPath, int userId);
- boolean verifyIdmap(@utf8InCpp String overlayApkPath, int userId);
+ boolean verifyIdmap(@utf8InCpp String overlayApkPath, int fulfilledPolicies,
+ boolean enforceOverlayable, int userId);
@nullable @utf8InCpp String createIdmap(@utf8InCpp String targetApkPath,
- @utf8InCpp String overlayApkPath, int userId);
+ @utf8InCpp String overlayApkPath,
+ int fulfilledPolicies,
+ boolean enforceOverlayable,
+ int userId);
}
diff --git a/cmds/idmap2/include/idmap2/CommandLineOptions.h b/cmds/idmap2/include/idmap2/CommandLineOptions.h
index b93e71631d08..6db6bf9ea8ad 100644
--- a/cmds/idmap2/include/idmap2/CommandLineOptions.h
+++ b/cmds/idmap2/include/idmap2/CommandLineOptions.h
@@ -44,6 +44,8 @@ class CommandLineOptions {
std::vector<std::string>* value);
CommandLineOptions& OptionalOption(const std::string& name, const std::string& description,
std::string* value);
+ CommandLineOptions& OptionalOption(const std::string& name, const std::string& description,
+ std::vector<std::string>* value);
bool Parse(const std::vector<std::string>& argv, std::ostream& outError) const;
void Usage(std::ostream& out) const;
@@ -56,6 +58,7 @@ class CommandLineOptions {
COUNT_OPTIONAL,
COUNT_EXACTLY_ONCE,
COUNT_ONCE_OR_MORE,
+ COUNT_OPTIONAL_ONCE_OR_MORE,
} count;
bool argument;
};
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h
index b989e4c3f9d1..1666dc8a3bbd 100644
--- a/cmds/idmap2/include/idmap2/Idmap.h
+++ b/cmds/idmap2/include/idmap2/Idmap.h
@@ -57,6 +57,8 @@
#include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h"
+#include "idmap2/Policies.h"
+
namespace android::idmap2 {
class Idmap;
@@ -233,11 +235,10 @@ class Idmap {
// file is used; change this in the next version of idmap to use a named
// package instead; also update FromApkAssets to take additional parameters:
// the target and overlay package names
- static std::unique_ptr<const Idmap> FromApkAssets(const std::string& target_apk_path,
- const ApkAssets& target_apk_assets,
- const std::string& overlay_apk_path,
- const ApkAssets& overlay_apk_assets,
- std::ostream& out_error);
+ static std::unique_ptr<const Idmap> FromApkAssets(
+ const std::string& target_apk_path, const ApkAssets& target_apk_assets,
+ const std::string& overlay_apk_path, const ApkAssets& overlay_apk_assets,
+ const PolicyBitmask& fulfilled_policies, bool enforce_overlayable, std::ostream& out_error);
inline const std::unique_ptr<const IdmapHeader>& GetHeader() const {
return header_;
diff --git a/cmds/idmap2/include/idmap2/Policies.h b/cmds/idmap2/include/idmap2/Policies.h
new file mode 100644
index 000000000000..eecee25445e2
--- /dev/null
+++ b/cmds/idmap2/include/idmap2/Policies.h
@@ -0,0 +1,41 @@
+/*
+ * 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 <ostream>
+#include <string>
+#include <vector>
+
+#include "androidfw/ResourceTypes.h"
+#include "androidfw/StringPiece.h"
+
+#include "Result.h"
+
+#ifndef IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
+#define IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
+
+namespace android::idmap2 {
+
+using PolicyFlags = ResTable_overlayable_policy_header::PolicyFlags;
+using PolicyBitmask = uint32_t;
+
+// Parses a the string representation of a set of policies into a bitmask. The format of the string
+// is the same as for the <policy> element.
+Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies,
+ std::ostream& err);
+
+} // namespace android::idmap2
+
+#endif // IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
diff --git a/cmds/idmap2/libidmap2/CommandLineOptions.cpp b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
index cabc8f398c46..a49a607091a4 100644
--- a/cmds/idmap2/libidmap2/CommandLineOptions.cpp
+++ b/cmds/idmap2/libidmap2/CommandLineOptions.cpp
@@ -68,9 +68,18 @@ CommandLineOptions& CommandLineOptions::OptionalOption(const std::string& name,
return *this;
}
+CommandLineOptions& CommandLineOptions::OptionalOption(const std::string& name,
+ const std::string& description,
+ std::vector<std::string>* value) {
+ assert(value != nullptr);
+ auto func = [value](const std::string& arg) -> void { value->push_back(arg); };
+ options_.push_back(Option{name, description, func, Option::COUNT_OPTIONAL_ONCE_OR_MORE, true});
+ return *this;
+}
+
bool CommandLineOptions::Parse(const std::vector<std::string>& argv, std::ostream& outError) const {
const auto pivot = std::partition(options_.begin(), options_.end(), [](const Option& opt) {
- return opt.count != Option::COUNT_OPTIONAL;
+ return opt.count != Option::COUNT_OPTIONAL && opt.count != Option::COUNT_OPTIONAL_ONCE_OR_MORE;
});
std::set<std::string> mandatory_opts;
std::transform(options_.begin(), pivot, std::inserter(mandatory_opts, mandatory_opts.end()),
@@ -122,7 +131,8 @@ void CommandLineOptions::Usage(std::ostream& out) const {
size_t maxLength = 0;
out << "usage: " << name_;
for (const Option& opt : options_) {
- const bool mandatory = opt.count != Option::COUNT_OPTIONAL;
+ const bool mandatory =
+ opt.count != Option::COUNT_OPTIONAL && opt.count != Option::COUNT_OPTIONAL_ONCE_OR_MORE;
out << " ";
if (!mandatory) {
out << "[";
@@ -134,9 +144,15 @@ void CommandLineOptions::Usage(std::ostream& out) const {
out << opt.name;
maxLength = std::max(maxLength, opt.name.size());
}
+
+ if (opt.count == Option::COUNT_OPTIONAL_ONCE_OR_MORE) {
+ out << " [..]";
+ }
+
if (!mandatory) {
out << "]";
}
+
if (opt.count == Option::COUNT_ONCE_OR_MORE) {
out << " [" << opt.name << " arg [..]]";
}
@@ -150,7 +166,8 @@ void CommandLineOptions::Usage(std::ostream& out) const {
out << opt.name;
}
out << " " << opt.description;
- if (opt.count == Option::COUNT_ONCE_OR_MORE) {
+ if (opt.count == Option::COUNT_ONCE_OR_MORE ||
+ opt.count == Option::COUNT_OPTIONAL_ONCE_OR_MORE) {
out << " (can be provided multiple times)";
}
out << std::endl;
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 37d6af8fa477..2890ae11b0af 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -274,11 +274,23 @@ std::unique_ptr<const Idmap> Idmap::FromBinaryStream(std::istream& stream,
return std::move(idmap);
}
-std::unique_ptr<const Idmap> Idmap::FromApkAssets(const std::string& target_apk_path,
- const ApkAssets& target_apk_assets,
- const std::string& overlay_apk_path,
- const ApkAssets& overlay_apk_assets,
- std::ostream& out_error) {
+bool CheckOverlayable(const LoadedPackage& target_package, PolicyBitmask fulfilled_polices,
+ ResourceId resid) {
+ const OverlayableInfo* info = target_package.GetOverlayableInfo(resid);
+ if (info == nullptr) {
+ // If the resource does not have an overlayable definition, allow the resource to be overlaid.
+ // Once overlayable enforcement is turned on, this check will return false.
+ return true;
+ }
+
+ // Enforce policy restrictions if the resource is declared as overlayable.
+ return (info->policy_flags & fulfilled_polices) != 0;
+}
+
+std::unique_ptr<const Idmap> Idmap::FromApkAssets(
+ const std::string& target_apk_path, const ApkAssets& target_apk_assets,
+ const std::string& overlay_apk_path, const ApkAssets& overlay_apk_assets,
+ const PolicyBitmask& fulfilled_policies, bool enforce_overlayable, std::ostream& out_error) {
AssetManager2 target_asset_manager;
if (!target_asset_manager.SetApkAssets({&target_apk_assets}, true, false)) {
out_error << "error: failed to create target asset manager" << std::endl;
@@ -380,6 +392,15 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets(const std::string& target_apk_
if (target_resid == 0) {
continue;
}
+
+ if (enforce_overlayable && !CheckOverlayable(*target_pkg, fulfilled_policies, target_resid)) {
+ // The resources must be defined as overlayable and the overlay must fulfill at least one
+ // policy enforced on the overlayable resource
+ LOG(WARNING) << "overlay \"" << overlay_apk_path << "\" is not allowed to overlay resource \""
+ << full_name << "\"" << std::endl;
+ continue;
+ }
+
matching_resources.Add(target_resid, overlay_resid);
}
diff --git a/cmds/idmap2/libidmap2/Policies.cpp b/cmds/idmap2/libidmap2/Policies.cpp
new file mode 100644
index 000000000000..0f87ef0c4ea9
--- /dev/null
+++ b/cmds/idmap2/libidmap2/Policies.cpp
@@ -0,0 +1,57 @@
+/*
+ * 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 <iterator>
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "androidfw/ResourceTypes.h"
+
+#include "idmap2/Idmap.h"
+#include "idmap2/Policies.h"
+#include "idmap2/Result.h"
+
+namespace android::idmap2 {
+
+namespace {
+
+const std::map<android::StringPiece, PolicyFlags> kStringToFlag = {
+ {"public", PolicyFlags::POLICY_PUBLIC},
+ {"product", PolicyFlags::POLICY_PRODUCT_PARTITION},
+ {"system", PolicyFlags::POLICY_SYSTEM_PARTITION},
+ {"vendor", PolicyFlags::POLICY_VENDOR_PARTITION},
+};
+} // namespace
+
+Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies,
+ std::ostream& err) {
+ PolicyBitmask bitmask = 0;
+ for (const std::string& policy : policies) {
+ const auto iter = kStringToFlag.find(policy);
+ if (iter != kStringToFlag.end()) {
+ bitmask |= iter->second;
+ } else {
+ err << "error: unknown policy \"" << policy << "\"";
+ return kResultError;
+ }
+ }
+
+ return Result<PolicyBitmask>(bitmask);
+}
+
+} // namespace android::idmap2
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
index 2698ac0a734d..35ec1ff1dbb5 100644
--- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -78,7 +78,8 @@ TEST(BinaryStreamVisitorTests, CreateIdmapFromApkAssetsInteropWithLoadedIdmap) {
std::stringstream error;
std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
ASSERT_THAT(idmap, NotNull());
std::stringstream stream;
@@ -101,25 +102,52 @@ TEST(BinaryStreamVisitorTests, CreateIdmapFromApkAssetsInteropWithLoadedIdmap) {
header = loaded_idmap->GetEntryMapForType(0x02);
ASSERT_THAT(header, NotNull());
- success = LoadedIdmap::Lookup(header, 0x0002, &entry);
+ success = LoadedIdmap::Lookup(header, 0x0000, &entry); // string/a
ASSERT_FALSE(success);
- success = LoadedIdmap::Lookup(header, 0x0003, &entry);
+ success = LoadedIdmap::Lookup(header, 0x0001, &entry); // string/b
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x0002, &entry); // string/c
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x0003, &entry); // string/not_overlayable
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x0004, &entry); // string/policy_product
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x0005, &entry); // string/policy_public
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x0006, &entry); // string/policy_system
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x0007, &entry); // string/policy_system_vendor
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x0008, &entry); // string/str1
ASSERT_TRUE(success);
ASSERT_EQ(entry, 0x0000);
- success = LoadedIdmap::Lookup(header, 0x0004, &entry);
+ success = LoadedIdmap::Lookup(header, 0x0009, &entry); // string/str2
ASSERT_FALSE(success);
- success = LoadedIdmap::Lookup(header, 0x0005, &entry);
+ success = LoadedIdmap::Lookup(header, 0x000a, &entry); // string/str3
ASSERT_TRUE(success);
ASSERT_EQ(entry, 0x0001);
- success = LoadedIdmap::Lookup(header, 0x0006, &entry);
+ success = LoadedIdmap::Lookup(header, 0x000b, &entry); // string/str4
ASSERT_TRUE(success);
ASSERT_EQ(entry, 0x0002);
- success = LoadedIdmap::Lookup(header, 0x0007, &entry);
+ success = LoadedIdmap::Lookup(header, 0x000c, &entry); // string/x
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x000d, &entry); // string/y
+ ASSERT_FALSE(success);
+
+ success = LoadedIdmap::Lookup(header, 0x000e, &entry); // string/z
ASSERT_FALSE(success);
}
diff --git a/cmds/idmap2/tests/CommandLineOptionsTests.cpp b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
index c27d27a16b94..39f18d3336af 100644
--- a/cmds/idmap2/tests/CommandLineOptionsTests.cpp
+++ b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
@@ -121,6 +121,56 @@ TEST(CommandLineOptionsTests, OptionalOption) {
ASSERT_FALSE(success);
}
+TEST(CommandLineOptionsTests, OptionalOptionList) {
+ std::vector<std::string> foo;
+ std::vector<std::string> bar;
+ CommandLineOptions opts = CommandLineOptions("test")
+ .OptionalOption("--foo", "", &foo)
+ .OptionalOption("--bar", "", &bar);
+ std::ostream fakeStdErr(nullptr);
+ bool success = opts.Parse({"--foo", "FOO", "--bar", "BAR"}, fakeStdErr);
+ ASSERT_TRUE(success);
+ ASSERT_EQ(foo.size(), 1U);
+ ASSERT_EQ(foo[0], "FOO");
+ ASSERT_EQ(bar.size(), 1U);
+ ASSERT_EQ(bar[0], "BAR");
+
+ foo.clear();
+ bar.clear();
+ success = opts.Parse({"--foo", "BAZ"}, fakeStdErr);
+ ASSERT_TRUE(success);
+ ASSERT_EQ(foo.size(), 1U);
+ ASSERT_EQ(foo[0], "BAZ");
+ ASSERT_EQ(bar.size(), 0U);
+
+ foo.clear();
+ bar.clear();
+ success =
+ opts.Parse({"--foo", "BAZ", "--foo", "BIZ", "--bar", "FIZ", "--bar", "FUZZ"}, fakeStdErr);
+ ASSERT_TRUE(success);
+ ASSERT_EQ(foo.size(), 2U);
+ ASSERT_EQ(foo[0], "BAZ");
+ ASSERT_EQ(foo[1], "BIZ");
+ ASSERT_EQ(bar.size(), 2U);
+ ASSERT_EQ(bar[0], "FIZ");
+ ASSERT_EQ(bar[1], "FUZZ");
+
+ foo.clear();
+ bar.clear();
+ success = opts.Parse({"--foo"}, fakeStdErr);
+ ASSERT_FALSE(success);
+
+ foo.clear();
+ bar.clear();
+ success = opts.Parse({"--foo", "--bar", "BAR"}, fakeStdErr);
+ ASSERT_FALSE(success);
+
+ foo.clear();
+ bar.clear();
+ success = opts.Parse({"--foo", "FOO", "--bar"}, fakeStdErr);
+ ASSERT_FALSE(success);
+}
+
TEST(CommandLineOptionsTests, CornerCases) {
std::string foo;
std::string bar;
@@ -172,6 +222,7 @@ TEST(CommandLineOptionsTests, Usage) {
bool arg5 = false;
bool arg6 = false;
std::vector<std::string> arg7;
+ std::vector<std::string> arg8;
CommandLineOptions opts = CommandLineOptions("test")
.MandatoryOption("--aa", "description-aa", &arg1)
.OptionalFlag("--bb", "description-bb", &arg5)
@@ -179,12 +230,13 @@ TEST(CommandLineOptionsTests, Usage) {
.OptionalOption("--dd", "description-dd", &arg3)
.MandatoryOption("--ee", "description-ee", &arg4)
.OptionalFlag("--ff", "description-ff", &arg6)
- .MandatoryOption("--gg", "description-gg", &arg7);
+ .MandatoryOption("--gg", "description-gg", &arg7)
+ .OptionalOption("--hh", "description-hh", &arg8);
std::stringstream stream;
opts.Usage(stream);
const std::string s = stream.str();
ASSERT_NE(s.find("usage: test --aa arg [--bb] [--cc arg] [--dd arg] --ee arg [--ff] --gg arg "
- "[--gg arg [..]]"),
+ "[--gg arg [..]] [--hh arg [..]]"),
std::string::npos);
ASSERT_NE(s.find("--aa arg description-aa"), std::string::npos);
ASSERT_NE(s.find("--ff description-ff"), std::string::npos);
diff --git a/cmds/idmap2/tests/FileUtilsTests.cpp b/cmds/idmap2/tests/FileUtilsTests.cpp
index 4bf832a34691..d9d9a7f829cf 100644
--- a/cmds/idmap2/tests/FileUtilsTests.cpp
+++ b/cmds/idmap2/tests/FileUtilsTests.cpp
@@ -37,10 +37,10 @@ TEST(FileUtilsTests, FindFilesFindEverythingNonRecursive) {
[](unsigned char type ATTRIBUTE_UNUSED,
const std::string& path ATTRIBUTE_UNUSED) -> bool { return true; });
ASSERT_THAT(v, NotNull());
- ASSERT_EQ(v->size(), 4U);
- ASSERT_EQ(
- std::set<std::string>(v->begin(), v->end()),
- std::set<std::string>({root + "/.", root + "/..", root + "/overlay", root + "/target"}));
+ ASSERT_EQ(v->size(), 6U);
+ ASSERT_EQ(std::set<std::string>(v->begin(), v->end()),
+ std::set<std::string>({root + "/.", root + "/..", root + "/overlay", root + "/target",
+ root + "/system-overlay", root + "/system-overlay-invalid"}));
}
TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) {
@@ -49,11 +49,13 @@ TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) {
return type == DT_REG && path.size() > 4 && path.compare(path.size() - 4, 4, ".apk") == 0;
});
ASSERT_THAT(v, NotNull());
- ASSERT_EQ(v->size(), 4U);
+ ASSERT_EQ(v->size(), 6U);
ASSERT_EQ(std::set<std::string>(v->begin(), v->end()),
std::set<std::string>({root + "/target/target.apk", root + "/overlay/overlay.apk",
root + "/overlay/overlay-static-1.apk",
- root + "/overlay/overlay-static-2.apk"}));
+ root + "/overlay/overlay-static-2.apk",
+ root + "/system-overlay/system-overlay.apk",
+ root + "/system-overlay-invalid/system-overlay-invalid.apk"}));
}
TEST(FileUtilsTests, ReadFile) {
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index 22f48e9a396f..0c8f164bf096 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -38,6 +38,7 @@
#include "gtest/gtest.h"
#include "androidfw/PosixUtils.h"
+
#include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h"
@@ -114,8 +115,9 @@ TEST_F(Idmap2BinaryTests, Dump) {
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
ASSERT_NE(result->stdout.find("0x7f010000 -> 0x7f010000 integer/int1"), std::string::npos);
- ASSERT_NE(result->stdout.find("0x7f020003 -> 0x7f020000 string/str1"), std::string::npos);
- ASSERT_NE(result->stdout.find("0x7f020005 -> 0x7f020001 string/str3"), std::string::npos);
+ ASSERT_NE(result->stdout.find("0x7f020008 -> 0x7f020000 string/str1"), std::string::npos);
+ ASSERT_NE(result->stdout.find("0x7f02000a -> 0x7f020001 string/str3"), std::string::npos);
+ ASSERT_NE(result->stdout.find("0x7f02000b -> 0x7f020002 string/str4"), std::string::npos);
ASSERT_EQ(result->stdout.find("00000210: 007f target package id"), std::string::npos);
// clang-format off
@@ -157,7 +159,8 @@ TEST_F(Idmap2BinaryTests, Scan) {
"--recursive",
"--target-package-name", "test.target",
"--target-apk-path", GetTargetApkPath(),
- "--output-directory", GetTempDirPath()});
+ "--output-directory", GetTempDirPath(),
+ "--override-policy", "public"});
// clang-format on
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
@@ -190,7 +193,8 @@ TEST_F(Idmap2BinaryTests, Scan) {
"--input-directory", GetTestDataPath() + "/overlay",
"--target-package-name", "test.target",
"--target-apk-path", GetTargetApkPath(),
- "--output-directory", GetTempDirPath()});
+ "--output-directory", GetTempDirPath(),
+ "--override-policy", "public"});
// clang-format on
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
@@ -207,7 +211,8 @@ TEST_F(Idmap2BinaryTests, Scan) {
"--recursive",
"--target-package-name", "test.target",
"--target-apk-path", GetTargetApkPath(),
- "--output-directory", GetTempDirPath()});
+ "--output-directory", GetTempDirPath(),
+ "--override-policy", "public"});
// clang-format on
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
@@ -222,7 +227,8 @@ TEST_F(Idmap2BinaryTests, Scan) {
"--input-directory", GetTempDirPath(),
"--target-package-name", "test.target",
"--target-apk-path", GetTargetApkPath(),
- "--output-directory", GetTempDirPath()});
+ "--output-directory", GetTempDirPath(),
+ "--override-policy", "public"});
// clang-format on
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
@@ -245,7 +251,7 @@ TEST_F(Idmap2BinaryTests, Lookup) {
"lookup",
"--idmap-path", GetIdmapPath(),
"--config", "",
- "--resid", "0x7f020003"}); // string/str1
+ "--resid", "0x7f020008"}); // string/str1
// clang-format on
ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;
@@ -310,6 +316,18 @@ TEST_F(Idmap2BinaryTests, InvalidCommandLineOptions) {
// clang-format on
ASSERT_THAT(result, NotNull());
ASSERT_NE(result->status, EXIT_SUCCESS);
+
+ // unknown policy
+ // clang-format off
+ result = ExecuteBinary({"idmap2",
+ "create",
+ "--target-apk-path", GetTargetApkPath(),
+ "--overlay-apk-path", GetOverlayApkPath(),
+ "--idmap-path", GetIdmapPath(),
+ "--policy", "this-does-not-exist"});
+ // clang-format on
+ ASSERT_THAT(result, NotNull());
+ ASSERT_NE(result->status, EXIT_SUCCESS);
}
} // namespace android::idmap2
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 963f22ec8d72..c6eb71cbeb72 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -184,13 +184,14 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) {
std::stringstream error;
std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
ASSERT_THAT(idmap, NotNull());
ASSERT_THAT(idmap->GetHeader(), NotNull());
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
- ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xf5ad1d1d);
+ ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xca2093da);
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0xd470336b);
ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path);
ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
@@ -216,13 +217,127 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) {
ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
ASSERT_EQ(types[1]->GetEntryCount(), 4U);
- ASSERT_EQ(types[1]->GetEntryOffset(), 3U);
+ ASSERT_EQ(types[1]->GetEntryOffset(), 8U);
ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
}
+TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
+ const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
+ std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+ ASSERT_THAT(target_apk, NotNull());
+
+ const std::string overlay_apk_path(GetTestDataPath() + "/system-overlay/system-overlay.apk");
+ std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+ ASSERT_THAT(overlay_apk, NotNull());
+
+ std::stringstream error;
+ std::unique_ptr<const Idmap> idmap =
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+ /* enforce_overlayable */ true, error);
+ ASSERT_THAT(idmap, NotNull());
+
+ const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+ ASSERT_EQ(dataBlocks.size(), 1U);
+
+ const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+
+ ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+ ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
+
+ const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+ ASSERT_EQ(types.size(), 1U);
+
+ ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
+ ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
+ ASSERT_EQ(types[0]->GetEntryCount(), 3U);
+ ASSERT_EQ(types[0]->GetEntryOffset(), 5U);
+ ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/policy_public
+ ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/policy_system
+ ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_system_vendor
+}
+
+TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
+ const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
+ std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+ ASSERT_THAT(target_apk, NotNull());
+
+ const std::string overlay_apk_path(GetTestDataPath() +
+ "/system-overlay-invalid/system-overlay-invalid.apk");
+ std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+ ASSERT_THAT(overlay_apk, NotNull());
+
+ std::stringstream error;
+ std::unique_ptr<const Idmap> idmap =
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+ /* enforce_overlayable */ true, error);
+ ASSERT_THAT(idmap, NotNull());
+
+ const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+ ASSERT_EQ(dataBlocks.size(), 1U);
+
+ const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+
+ ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+ ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
+
+ const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+ ASSERT_EQ(types.size(), 1U);
+
+ ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
+ ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
+ ASSERT_EQ(types[0]->GetEntryCount(), 5U);
+ ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
+ ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable
+ ASSERT_EQ(types[0]->GetEntry(1), kNoEntry); // string/policy_product
+ ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_public
+ ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_system
+ ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_system_vendor
+}
+
+TEST(IdmapTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
+ const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
+ std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+ ASSERT_THAT(target_apk, NotNull());
+
+ const std::string overlay_apk_path(GetTestDataPath() +
+ "/system-overlay-invalid/system-overlay-invalid.apk");
+ std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+ ASSERT_THAT(overlay_apk, NotNull());
+
+ std::stringstream error;
+ std::unique_ptr<const Idmap> idmap =
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
+ /* enforce_overlayable */ false, error);
+ ASSERT_THAT(idmap, NotNull());
+
+ const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+ ASSERT_EQ(dataBlocks.size(), 1U);
+
+ const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+
+ ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+ ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U);
+
+ const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
+ ASSERT_EQ(types.size(), 1U);
+
+ ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
+ ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
+ ASSERT_EQ(types[0]->GetEntryCount(), 5U);
+ ASSERT_EQ(types[0]->GetEntryOffset(), 3U);
+ ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable
+ ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/policy_product
+ ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_public
+ ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_system
+ ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_system_vendor
+}
+
TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
std::string target_apk_path(GetTestDataPath());
for (int i = 0; i < 32; i++) {
@@ -239,7 +354,8 @@ TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
std::stringstream error;
std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
ASSERT_THAT(idmap, IsNull());
}
@@ -255,8 +371,9 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) {
ASSERT_THAT(overlay_apk, NotNull());
std::stringstream error;
- std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+ std::unique_ptr<const Idmap> idmap = Idmap::FromApkAssets(
+ target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
+ /* enforce_overlayable */ true, error);
ASSERT_THAT(idmap, NotNull());
std::stringstream stream;
diff --git a/cmds/idmap2/tests/PoliciesTests.cpp b/cmds/idmap2/tests/PoliciesTests.cpp
new file mode 100644
index 000000000000..ab567adc6f19
--- /dev/null
+++ b/cmds/idmap2/tests/PoliciesTests.cpp
@@ -0,0 +1,70 @@
+/*
+ * 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 <string>
+
+#include "gtest/gtest.h"
+
+#include "TestHelpers.h"
+#include "idmap2/Policies.h"
+
+using android::idmap2::PolicyBitmask;
+using android::idmap2::PolicyFlags;
+
+namespace android::idmap2 {
+
+TEST(PoliciesTests, PoliciesToBitmasks) {
+ const Result<PolicyBitmask> bitmask1 = PoliciesToBitmask({"system"}, std::cerr);
+ ASSERT_NE(bitmask1, kResultError);
+ ASSERT_EQ(bitmask1, PolicyFlags::POLICY_SYSTEM_PARTITION);
+
+ const Result<PolicyBitmask> bitmask2 = PoliciesToBitmask({"system", "vendor"}, std::cerr);
+ ASSERT_NE(bitmask2, kResultError);
+ ASSERT_EQ(bitmask2, PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION);
+
+ const Result<PolicyBitmask> bitmask3 = PoliciesToBitmask({"vendor", "system"}, std::cerr);
+ ASSERT_NE(bitmask3, kResultError);
+ ASSERT_EQ(bitmask3, PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION);
+
+ const Result<PolicyBitmask> bitmask4 =
+ PoliciesToBitmask({"public", "product", "system", "vendor"}, std::cerr);
+ ASSERT_NE(bitmask4, kResultError);
+ ASSERT_EQ(bitmask4, PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_PRODUCT_PARTITION |
+ PolicyFlags::POLICY_SYSTEM_PARTITION |
+ PolicyFlags::POLICY_VENDOR_PARTITION);
+
+ const Result<PolicyBitmask> bitmask5 =
+ PoliciesToBitmask({"system", "system", "system"}, std::cerr);
+ ASSERT_NE(bitmask5, kResultError);
+ ASSERT_EQ(bitmask5, PolicyFlags::POLICY_SYSTEM_PARTITION);
+
+ const Result<PolicyBitmask> bitmask6 = PoliciesToBitmask({""}, std::cerr);
+ ASSERT_EQ(bitmask6, kResultError);
+
+ const Result<PolicyBitmask> bitmask7 = PoliciesToBitmask({"foo"}, std::cerr);
+ ASSERT_EQ(bitmask7, kResultError);
+
+ const Result<PolicyBitmask> bitmask8 = PoliciesToBitmask({"system", "foo"}, std::cerr);
+ ASSERT_EQ(bitmask8, kResultError);
+
+ const Result<PolicyBitmask> bitmask9 = PoliciesToBitmask({"system", ""}, std::cerr);
+ ASSERT_EQ(bitmask9, kResultError);
+
+ const Result<PolicyBitmask> bitmask10 = PoliciesToBitmask({"system "}, std::cerr);
+ ASSERT_EQ(bitmask10, kResultError);
+}
+
+} // namespace android::idmap2
diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
index 7736bc063131..eaa47cd79533 100644
--- a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
@@ -25,6 +25,7 @@
#include "androidfw/Idmap.h"
#include "idmap2/Idmap.h"
+#include "idmap2/Policies.h"
#include "idmap2/PrettyPrintVisitor.h"
#include "TestHelpers.h"
@@ -32,6 +33,7 @@
using ::testing::NotNull;
using android::ApkAssets;
+using android::idmap2::PolicyBitmask;
namespace android::idmap2 {
@@ -46,7 +48,8 @@ TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitor) {
std::stringstream error;
std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
ASSERT_THAT(idmap, NotNull());
std::stringstream stream;
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index 0318cd20a9bb..b58c61a0c284 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -42,7 +42,8 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
std::stringstream error;
std::unique_ptr<const Idmap> idmap =
- Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk, error);
+ Idmap::FromApkAssets(target_apk_path, *target_apk, overlay_apk_path, *overlay_apk,
+ PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true, error);
ASSERT_THAT(idmap, NotNull());
std::stringstream stream;
@@ -51,7 +52,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
ASSERT_NE(stream.str().find("00000000: 504d4449 magic\n"), std::string::npos);
ASSERT_NE(stream.str().find("00000004: 00000001 version\n"), std::string::npos);
- ASSERT_NE(stream.str().find("00000008: f5ad1d1d target crc\n"), std::string::npos);
+ ASSERT_NE(stream.str().find("00000008: ca2093da target crc\n"), std::string::npos);
ASSERT_NE(stream.str().find("0000000c: d470336b overlay crc\n"), std::string::npos);
ASSERT_NE(stream.str().find("0000021c: 00000000 0x7f010000 -> 0x7f010000 integer/int1\n"),
std::string::npos);
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml b/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml
new file mode 100644
index 000000000000..977cd97f21c3
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay-invalid/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.overlay.system.invalid">
+ <overlay
+ android:targetPackage="test.target" />
+</manifest>
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/build b/cmds/idmap2/tests/data/system-overlay-invalid/build
new file mode 100644
index 000000000000..920e1f8ad6f3
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay-invalid/build
@@ -0,0 +1,26 @@
+# 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.
+
+FRAMEWORK_RES_APK=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar
+
+aapt2 compile --dir res -o compiled.flata
+
+aapt2 link \
+ --no-resource-removal \
+ -I "$FRAMEWORK_RES_APK" \
+ --manifest AndroidManifest.xml \
+ -o system-overlay-invalid.apk \
+ compiled.flata
+
+rm compiled.flata
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml b/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml
new file mode 100644
index 000000000000..512770722a4b
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <!-- This overlay will fulfill the policies "public|system". This allows it overlay the
+ following resources. -->
+ <string name="policy_system">policy_system</string>
+ <string name="policy_system_vendor">policy_system_vendor</string>
+ <string name="policy_public">policy_public</string>
+
+ <!-- It also requests to overlay a resource that belongs to a policy the overlay does not
+ fulfill.-->
+ <string name="policy_product">policy_product</string>
+
+ <!-- It also requests to overlay a resource that is not declared as overlayable.-->
+ <string name="not_overlayable">not_overlayable</string>
+</resources>
diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk b/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk
new file mode 100644
index 000000000000..c367f82e21e6
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml b/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml
new file mode 100644
index 000000000000..8af9064ba64f
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="test.overlay.system">
+ <overlay
+ android:targetPackage="test.target" />
+</manifest>
diff --git a/cmds/idmap2/tests/data/system-overlay/build b/cmds/idmap2/tests/data/system-overlay/build
new file mode 100644
index 000000000000..be0d2390f535
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay/build
@@ -0,0 +1,26 @@
+# 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.
+
+FRAMEWORK_RES_APK=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/public/android.jar
+
+aapt2 compile --dir res -o compiled.flata
+
+aapt2 link \
+ --no-resource-removal \
+ -I "$FRAMEWORK_RES_APK" \
+ --manifest AndroidManifest.xml \
+ -o system-overlay.apk \
+ compiled.flata
+
+rm compiled.flata
diff --git a/cmds/idmap2/tests/data/system-overlay/res/values/values.xml b/cmds/idmap2/tests/data/system-overlay/res/values/values.xml
new file mode 100644
index 000000000000..6aaa0b02639e
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay/res/values/values.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+ <!-- This overlay will fulfill the policies "public|system". This allows it overlay the
+ following resources. -->
+ <string name="policy_system">policy_system</string>
+ <string name="policy_system_vendor">policy_system_vendor</string>
+ <string name="policy_public">policy_public</string>
+</resources>
diff --git a/cmds/idmap2/tests/data/system-overlay/system-overlay.apk b/cmds/idmap2/tests/data/system-overlay/system-overlay.apk
new file mode 100644
index 000000000000..90f30eb68c15
--- /dev/null
+++ b/cmds/idmap2/tests/data/system-overlay/system-overlay.apk
Binary files differ
diff --git a/cmds/idmap2/tests/data/target/res/values/overlayable.xml b/cmds/idmap2/tests/data/target/res/values/overlayable.xml
new file mode 100644
index 000000000000..de19e6fcd022
--- /dev/null
+++ b/cmds/idmap2/tests/data/target/res/values/overlayable.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<resources>
+<overlayable name="TestResources">
+ <!-- Publicly overlayable resources -->
+ <item type="string" name="a" />
+ <item type="string" name="b" />
+ <item type="string" name="c" />
+ <item type="string" name="str1" />
+ <item type="string" name="str2" />
+ <item type="string" name="str3" />
+ <item type="string" name="str4" />
+ <item type="string" name="x" />
+ <item type="string" name="y" />
+ <item type="string" name="z" />
+ <item type="integer" name="int1" />
+
+ <!-- Resources with partition restrictins -->
+ <policy type="system">
+ <item type="string" name="policy_system" />
+ </policy>
+
+ <policy type="system|vendor">
+ <item type="string" name="policy_system_vendor" />
+ </policy>
+
+ <policy type="product">
+ <item type="string" name="policy_product" />
+ </policy>
+
+ <policy type="public">
+ <item type="string" name="policy_public" />
+ </policy>
+</overlayable>
+</resources> \ No newline at end of file
diff --git a/cmds/idmap2/tests/data/target/res/values/values.xml b/cmds/idmap2/tests/data/target/res/values/values.xml
index 56bf0d60021a..ef9012e49300 100644
--- a/cmds/idmap2/tests/data/target/res/values/values.xml
+++ b/cmds/idmap2/tests/data/target/res/values/values.xml
@@ -25,4 +25,12 @@
<string name="y">y</string>
<string name="z">z</string>
<integer name="int1">1</integer>
+
+ <!-- This resources is not marked as overlayable -->
+ <string name="not_overlayable">not_overlayable</string>
+
+ <string name="policy_system">policy_system</string>
+ <string name="policy_system_vendor">policy_system_vendor</string>
+ <string name="policy_product">policy_product</string>
+ <string name="policy_public">policy_public</string>
</resources>
diff --git a/cmds/idmap2/tests/data/target/target.apk b/cmds/idmap2/tests/data/target/target.apk
index 18ecc276caae..9a6220dbe3ca 100644
--- a/cmds/idmap2/tests/data/target/target.apk
+++ b/cmds/idmap2/tests/data/target/target.apk
Binary files differ
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 7e2df275515e..0a8746a639fc 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -3331,7 +3331,8 @@ message PackageAssociationSourceProcessStatsProto {
optional int32 process_uid = 1;
// Process name.
optional string process_name = 2;
-
+ // Package name.
+ optional string package_name = 7;
// Total count of the times this association appeared.
optional int32 total_count = 3;
@@ -3410,6 +3411,9 @@ message ProcessStatsSectionProto {
}
repeated Status status = 7;
+ // Number of pages available of various types and sizes, representation fragmentation.
+ repeated ProcessStatsAvailablePagesProto available_pages = 10;
+
// Stats for each process.
repeated ProcessStatsProto process_stats = 8;
@@ -3417,6 +3421,21 @@ message ProcessStatsSectionProto {
repeated ProcessStatsPackageProto package_stats = 9;
}
+message ProcessStatsAvailablePagesProto {
+ // Node these pages are in (as per /proc/pagetypeinfo)
+ optional int32 node = 1;
+
+ // Zone these pages are in (as per /proc/pagetypeinfo)
+ optional string zone = 2;
+
+ // Label for the type of these pages (as per /proc/pagetypeinfo)
+ optional string label = 3;
+
+ // Distribution of number of pages available by order size. First entry in array is
+ // order 0, second is order 1, etc. Each order increase is a doubling of page size.
+ repeated int32 pages_per_order = 4;
+}
+
/**
* Pulled from ProcessStatsService.java
*/
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 5392a3c428c1..02eff0b6cee2 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -1108,18 +1108,6 @@ Landroid/os/UserManager;->isUserUnlocked(I)Z
Landroid/os/UserManager;->mService:Landroid/os/IUserManager;
Landroid/os/UserManager;->removeUser(I)Z
Landroid/os/Vibrator;-><init>()V
-Landroid/os/VintfObject;->getHalNamesAndVersions()[Ljava/lang/String;
-Landroid/os/VintfObject;->getSepolicyVersion()Ljava/lang/String;
-Landroid/os/VintfObject;->getTargetFrameworkCompatibilityMatrixVersion()Ljava/lang/Long;
-Landroid/os/VintfObject;->getVndkSnapshots()Ljava/util/Map;
-Landroid/os/VintfObject;->report()[Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getCpuInfo()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getHardwareId()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getKernelVersion()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getNodeName()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getOsName()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getOsRelease()Ljava/lang/String;
-Landroid/os/VintfRuntimeInfo;->getOsVersion()Ljava/lang/String;
Landroid/os/WorkSource;-><init>(Landroid/os/Parcel;)V
Landroid/os/WorkSource;->mNames:[Ljava/lang/String;
Landroid/os/WorkSource;->mNum:I
@@ -1824,22 +1812,10 @@ Lcom/android/internal/os/RuntimeInit;->getApplicationObject()Landroid/os/IBinder
Lcom/android/internal/os/RuntimeInit;->initialized:Z
Lcom/android/internal/os/RuntimeInit;->main([Ljava/lang/String;)V
Lcom/android/internal/os/RuntimeInit;->mApplicationObject:Landroid/os/IBinder;
-Lcom/android/internal/os/ZygoteConnection$Arguments;-><init>([Ljava/lang/String;)V
-Lcom/android/internal/os/ZygoteConnection$Arguments;->effectiveCapabilities:J
-Lcom/android/internal/os/ZygoteConnection$Arguments;->gid:I
-Lcom/android/internal/os/ZygoteConnection$Arguments;->gids:[I
-Lcom/android/internal/os/ZygoteConnection$Arguments;->permittedCapabilities:J
-Lcom/android/internal/os/ZygoteConnection$Arguments;->remainingArgs:[Ljava/lang/String;
-Lcom/android/internal/os/ZygoteConnection$Arguments;->rlimits:Ljava/util/ArrayList;
-Lcom/android/internal/os/ZygoteConnection$Arguments;->uid:I
-Lcom/android/internal/os/ZygoteConnection;->applyUidSecurityPolicy(Lcom/android/internal/os/ZygoteConnection$Arguments;Landroid/net/Credentials;)V
Lcom/android/internal/os/ZygoteConnection;->closeSocket()V
-Lcom/android/internal/os/ZygoteConnection;->getFileDesciptor()Ljava/io/FileDescriptor;
-Lcom/android/internal/os/ZygoteConnection;->intArray2d:[[I
Lcom/android/internal/os/ZygoteConnection;->mSocket:Landroid/net/LocalSocket;
Lcom/android/internal/os/ZygoteConnection;->mSocketOutStream:Ljava/io/DataOutputStream;
Lcom/android/internal/os/ZygoteConnection;->peer:Landroid/net/Credentials;
-Lcom/android/internal/os/ZygoteConnection;->readArgumentList()[Ljava/lang/String;
Lcom/android/internal/os/ZygoteInit;->main([Ljava/lang/String;)V
Lcom/android/internal/os/ZygoteInit;->mResources:Landroid/content/res/Resources;
Lcom/android/internal/os/ZygoteSecurityException;-><init>(Ljava/lang/String;)V
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index ec2e2fd474a2..fe68b8a048c2 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
+import android.app.Person;
import android.app.TaskStackBuilder;
import android.content.ComponentName;
import android.content.Context;
@@ -111,6 +112,9 @@ public final class ShortcutInfo implements Parcelable {
public static final int FLAG_SHADOW = 1 << 12;
/** @hide */
+ public static final int FLAG_LONG_LIVED = 1 << 13;
+
+ /** @hide */
@IntDef(flag = true, prefix = { "FLAG_" }, value = {
FLAG_DYNAMIC,
FLAG_PINNED,
@@ -124,6 +128,8 @@ public final class ShortcutInfo implements Parcelable {
FLAG_ADAPTIVE_BITMAP,
FLAG_RETURNED_BY_SERVICE,
FLAG_ICON_FILE_PENDING_SAVE,
+ FLAG_SHADOW,
+ FLAG_LONG_LIVED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ShortcutFlags {}
@@ -344,6 +350,9 @@ public final class ShortcutInfo implements Parcelable {
@Nullable
private PersistableBundle[] mIntentPersistableExtrases;
+ @Nullable
+ private Person[] mPersons;
+
private int mRank;
/**
@@ -399,6 +408,10 @@ public final class ShortcutInfo implements Parcelable {
mCategories = cloneCategories(b.mCategories);
mIntents = cloneIntents(b.mIntents);
fixUpIntentExtras();
+ mPersons = clonePersons(b.mPersons);
+ if (b.mIsLongLived) {
+ setLongLived();
+ }
mRank = b.mRank;
mExtras = b.mExtras;
updateTimestamp();
@@ -465,6 +478,20 @@ public final class ShortcutInfo implements Parcelable {
return ret;
}
+ private static Person[] clonePersons(Person[] persons) {
+ if (persons == null) {
+ return null;
+ }
+ final Person[] ret = new Person[persons.length];
+ for (int i = 0; i < ret.length; i++) {
+ if (persons[i] != null) {
+ // Don't need to keep the icon, remove it to save space
+ ret[i] = persons[i].toBuilder().setIcon(null).build();
+ }
+ }
+ return ret;
+ }
+
/**
* Throws if any of the mandatory fields is not set.
*
@@ -511,6 +538,7 @@ public final class ShortcutInfo implements Parcelable {
mDisabledMessage = source.mDisabledMessage;
mDisabledMessageResId = source.mDisabledMessageResId;
mCategories = cloneCategories(source.mCategories);
+ mPersons = clonePersons(source.mPersons);
if ((cloneFlags & CLONE_REMOVE_INTENT) == 0) {
mIntents = cloneIntents(source.mIntents);
mIntentPersistableExtrases =
@@ -833,6 +861,9 @@ public final class ShortcutInfo implements Parcelable {
if (source.mCategories != null) {
mCategories = cloneCategories(source.mCategories);
}
+ if (source.mPersons != null) {
+ mPersons = clonePersons(source.mPersons);
+ }
if (source.mIntents != null) {
mIntents = cloneIntents(source.mIntents);
mIntentPersistableExtrases =
@@ -901,6 +932,10 @@ public final class ShortcutInfo implements Parcelable {
private Intent[] mIntents;
+ private Person[] mPersons;
+
+ private boolean mIsLongLived;
+
private int mRank = RANK_NOT_SET;
private PersistableBundle mExtras;
@@ -1165,6 +1200,53 @@ public final class ShortcutInfo implements Parcelable {
}
/**
+ * Add a person that is relevant to this shortcut. Alternatively,
+ * {@link #setPersons(Person[])} can be used to add multiple persons to a shortcut.
+ *
+ * <p> This is an optional field, but the addition of person may cause this shortcut to
+ * appear more prominently in the user interface (e.g. ShareSheet).
+ *
+ * <p> A person should usually contain a uri in order to benefit from the ranking boost.
+ * However, even if no uri is provided, it's beneficial to provide people in the shortcut,
+ * such that listeners and voice only devices can announce and handle them properly.
+ *
+ * @see Person
+ * @see #setPersons(Person[])
+ */
+ @NonNull
+ public Builder setPerson(@NonNull Person person) {
+ return setPersons(new Person[]{person});
+ }
+
+ /**
+ * Sets multiple persons instead of a single person.
+ *
+ * @see Person
+ * @see #setPerson(Person)
+ */
+ @NonNull
+ public Builder setPersons(@NonNull Person[] persons) {
+ Preconditions.checkNotNull(persons, "persons cannot be null");
+ Preconditions.checkNotNull(persons.length, "persons cannot be empty");
+ for (Person person : persons) {
+ Preconditions.checkNotNull(person, "persons cannot contain null");
+ }
+ mPersons = clonePersons(persons);
+ return this;
+ }
+
+ /**
+ * Sets if a shortcut would be valid even if it has been unpublished/invisible by the app
+ * (as a dynamic or pinned shortcut). If it is long lived, it can be cached by various
+ * system services even after it has been unpublished as a dynamic shortcut.
+ */
+ @NonNull
+ public Builder setLongLived() {
+ mIsLongLived = true;
+ return this;
+ }
+
+ /**
* "Rank" of a shortcut, which is a non-negative value that's used by the launcher app
* to sort shortcuts.
*
@@ -1395,6 +1477,16 @@ public final class ShortcutInfo implements Parcelable {
}
/**
+ * Return the Persons set with {@link Builder#setPersons(Person[])}.
+ *
+ * @hide
+ */
+ @Nullable
+ public Person[] getPersons() {
+ return clonePersons(mPersons);
+ }
+
+ /**
* The extras in the intents. We convert extras into {@link PersistableBundle} so we can
* persist them.
* @hide
@@ -1525,6 +1617,16 @@ public final class ShortcutInfo implements Parcelable {
addFlags(FLAG_RETURNED_BY_SERVICE);
}
+ /** @hide */
+ public boolean isLongLived() {
+ return hasFlags(FLAG_LONG_LIVED);
+ }
+
+ /** @hide */
+ public void setLongLived() {
+ addFlags(FLAG_LONG_LIVED);
+ }
+
/** Return whether a shortcut is dynamic. */
public boolean isDynamic() {
return hasFlags(FLAG_DYNAMIC);
@@ -1893,6 +1995,8 @@ public final class ShortcutInfo implements Parcelable {
mCategories.add(source.readString().intern());
}
}
+
+ mPersons = source.readParcelableArray(cl, Person.class);
}
@Override
@@ -1940,6 +2044,8 @@ public final class ShortcutInfo implements Parcelable {
} else {
dest.writeInt(0);
}
+
+ dest.writeParcelableArray(mPersons, flags);
}
public static final Creator<ShortcutInfo> CREATOR =
@@ -2040,6 +2146,9 @@ public final class ShortcutInfo implements Parcelable {
if (isReturnedByServer()) {
sb.append("Rets");
}
+ if (isLongLived()) {
+ sb.append("Liv");
+ }
sb.append("]");
addIndentOrComma(sb, indent);
@@ -2094,6 +2203,11 @@ public final class ShortcutInfo implements Parcelable {
addIndentOrComma(sb, indent);
+ sb.append("persons=");
+ sb.append(mPersons);
+
+ addIndentOrComma(sb, indent);
+
sb.append("icon=");
sb.append(mIcon);
diff --git a/core/java/android/os/VintfObject.java b/core/java/android/os/VintfObject.java
index fb22194098b6..23c54f450a67 100644
--- a/core/java/android/os/VintfObject.java
+++ b/core/java/android/os/VintfObject.java
@@ -16,23 +16,27 @@
package android.os;
-import java.util.Map;
+import android.annotation.TestApi;
+import java.util.Map;
/**
* Java API for libvintf.
+ *
* @hide
*/
+@TestApi
public class VintfObject {
- /// ---------- OTA
-
/**
* Slurps all device information (both manifests and both matrices)
* and report them.
* If any error in getting one of the manifests, it is not included in
* the list.
+ *
+ * @hide
*/
+ @TestApi
public static native String[] report();
/**
@@ -44,6 +48,8 @@ public class VintfObject {
* @return = 0 if success (compatible)
* > 0 if incompatible
* < 0 if any error (mount partition fails, illformed XML, etc.)
+ *
+ * @hide
*/
public static native int verify(String[] packageInfo);
@@ -55,22 +61,28 @@ public class VintfObject {
* @return = 0 if success (compatible)
* > 0 if incompatible
* < 0 if any error (mount partition fails, illformed XML, etc.)
+ *
+ * @hide
*/
public static native int verifyWithoutAvb();
- /// ---------- CTS Device Info
-
/**
* @return a list of HAL names and versions that is supported by this
* device as stated in device and framework manifests. For example,
* ["android.hidl.manager@1.0", "android.hardware.camera.device@1.0",
* "android.hardware.camera.device@3.2"]. There are no duplicates.
+ *
+ * @hide
*/
+ @TestApi
public static native String[] getHalNamesAndVersions();
/**
* @return the BOARD_SEPOLICY_VERS build flag available in device manifest.
+ *
+ * @hide
*/
+ @TestApi
public static native String getSepolicyVersion();
/**
@@ -78,13 +90,22 @@ public class VintfObject {
* specified in framework manifest. For example,
* [("27", ["libjpeg.so", "libbase.so"]),
* ("28", ["libjpeg.so", "libbase.so"])]
+ *
+ * @hide
*/
+ @TestApi
public static native Map<String, String[]> getVndkSnapshots();
/**
- * @return target FCM version, a number specified in the device manifest
- * indicating the FCM version that the device manifest implements. Null if
- * device manifest doesn't specify this number (for legacy devices).
+ * @return Target Framework Compatibility Matrix (FCM) version, a number
+ * specified in the device manifest indicating the FCM version that the
+ * device manifest implements. Null if device manifest doesn't specify this
+ * number (for legacy devices).
+ *
+ * @hide
*/
+ @TestApi
public static native Long getTargetFrameworkCompatibilityMatrixVersion();
+
+ private VintfObject() {}
}
diff --git a/core/java/android/os/VintfRuntimeInfo.java b/core/java/android/os/VintfRuntimeInfo.java
index 29698b9fa684..f17039ba9bf4 100644
--- a/core/java/android/os/VintfRuntimeInfo.java
+++ b/core/java/android/os/VintfRuntimeInfo.java
@@ -16,55 +16,84 @@
package android.os;
+import android.annotation.TestApi;
+
/**
* Java API for ::android::vintf::RuntimeInfo. Methods return null / 0 on any error.
*
* @hide
*/
+@TestApi
public class VintfRuntimeInfo {
private VintfRuntimeInfo() {}
/**
* @return /sys/fs/selinux/policyvers, via security_policyvers() native call
+ *
+ * @hide
*/
public static native long getKernelSepolicyVersion();
/**
* @return content of /proc/cpuinfo
+ *
+ * @hide
*/
+ @TestApi
public static native String getCpuInfo();
/**
* @return os name extracted from uname() native call
+ *
+ * @hide
*/
+ @TestApi
public static native String getOsName();
/**
* @return node name extracted from uname() native call
+ *
+ * @hide
*/
+ @TestApi
public static native String getNodeName();
/**
* @return os release extracted from uname() native call
+ *
+ * @hide
*/
+ @TestApi
public static native String getOsRelease();
/**
* @return os version extracted from uname() native call
+ *
+ * @hide
*/
+ @TestApi
public static native String getOsVersion();
/**
* @return hardware id extracted from uname() native call
+ *
+ * @hide
*/
+ @TestApi
public static native String getHardwareId();
/**
* @return kernel version extracted from uname() native call. Format is
* {@code x.y.z}.
+ *
+ * @hide
*/
+ @TestApi
public static native String getKernelVersion();
/**
* @return libavb version in OS. Format is {@code x.y}.
+ *
+ * @hide
*/
public static native String getBootAvbVersion();
/**
* @return libavb version in bootloader. Format is {@code x.y}.
+ *
+ * @hide
*/
public static native String getBootVbmetaAvbVersion();
-
}
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 44cb2212cd0c..af8146e85ec0 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -53,6 +53,13 @@ public final class DeviceConfig {
public static final Uri CONTENT_URI = Uri.parse("content://" + Settings.AUTHORITY + "/config");
/**
+ * Namespace for all Game Driver features.
+ * @hide
+ */
+ @SystemApi
+ public static final String NAMESPACE_GAME_DRIVER = "game_driver";
+
+ /**
* Namespace for all input-related features that are used at the native level.
* These features are applied at reboot.
*
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 878b6b642f7d..dc7c343c2c3e 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -22,6 +22,7 @@ import android.annotation.Nullable;
import android.annotation.SystemService;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
@@ -398,19 +399,31 @@ public abstract class LayoutInflater {
}
private void initPrecompiledViews() {
+ // Check if precompiled layouts are enabled by a system property.
+ mUseCompiledView =
+ SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false);
+ if (!mUseCompiledView) {
+ return;
+ }
+
+ // Make sure the application allows code generation
+ ApplicationInfo appInfo = mContext.getApplicationInfo();
+ if ((appInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PREFER_CODE_INTEGRITY) != 0
+ || appInfo.isPrivilegedApp()) {
+ mUseCompiledView = false;
+ return;
+ }
+
+ // Try to load the precompiled layout file.
try {
- mUseCompiledView =
- SystemProperties.getBoolean(USE_PRECOMPILED_LAYOUT_SYSTEM_PROPERTY, false);
- if (mUseCompiledView) {
- mPrecompiledClassLoader = mContext.getClassLoader();
- String dexFile = mContext.getCodeCacheDir() + COMPILED_VIEW_DEX_FILE_NAME;
- if (new File(dexFile).exists()) {
- mPrecompiledClassLoader = new PathClassLoader(dexFile, mPrecompiledClassLoader);
- } else {
- // If the precompiled layout file doesn't exist, then disable precompiled
- // layouts.
- mUseCompiledView = false;
- }
+ mPrecompiledClassLoader = mContext.getClassLoader();
+ String dexFile = mContext.getCodeCacheDir() + COMPILED_VIEW_DEX_FILE_NAME;
+ if (new File(dexFile).exists()) {
+ mPrecompiledClassLoader = new PathClassLoader(dexFile, mPrecompiledClassLoader);
+ } else {
+ // If the precompiled layout file doesn't exist, then disable precompiled
+ // layouts.
+ mUseCompiledView = false;
}
} catch (Throwable e) {
if (DEBUG) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 273d89c8f10a..5e98236f7535 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -30,6 +30,7 @@ import static android.view.SurfaceControlProto.NAME;
import android.annotation.Size;
import android.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
+import android.graphics.ColorSpace;
import android.graphics.GraphicBuffer;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
@@ -141,6 +142,7 @@ public class SurfaceControl implements Parcelable {
private static native int nativeGetActiveConfig(IBinder displayToken);
private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
private static native int[] nativeGetDisplayColorModes(IBinder displayToken);
+ private static native int[] nativeGetCompositionDataspaces();
private static native int nativeGetActiveColorMode(IBinder displayToken);
private static native boolean nativeSetActiveColorMode(IBinder displayToken,
int colorMode);
@@ -375,6 +377,13 @@ public class SurfaceControl implements Parcelable {
*/
public static final int WINDOW_TYPE_DONT_SCREENSHOT = 441731;
+ /**
+ * internal representation of how to interpret pixel value, used only to convert to ColorSpace.
+ */
+ private static final int INTERNAL_DATASPACE_SRGB = 142671872;
+ private static final int INTERNAL_DATASPACE_DISPLAY_P3 = 143261696;
+ private static final int INTERNAL_DATASPACE_SCRGB = 411107328;
+
private void assignNativeObject(long nativeObject) {
if (mNativeObject != 0) {
release();
@@ -1517,6 +1526,35 @@ public class SurfaceControl implements Parcelable {
}
/**
+ * Returns an array of color spaces with 2 elements. The first color space is the
+ * default color space and second one is wide color gamut color space.
+ * @hide
+ */
+ public static ColorSpace[] getCompositionColorSpaces() {
+ int[] dataspaces = nativeGetCompositionDataspaces();
+ ColorSpace srgb = ColorSpace.get(ColorSpace.Named.SRGB);
+ ColorSpace[] colorSpaces = { srgb, srgb };
+ if (dataspaces.length == 2) {
+ for (int i = 0; i < 2; ++i) {
+ switch(dataspaces[i]) {
+ case INTERNAL_DATASPACE_DISPLAY_P3:
+ colorSpaces[i] = ColorSpace.get(ColorSpace.Named.DISPLAY_P3);
+ break;
+ case INTERNAL_DATASPACE_SCRGB:
+ colorSpaces[i] = ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB);
+ break;
+ case INTERNAL_DATASPACE_SRGB:
+ // Other dataspace is not recognized, use SRGB color space instead,
+ // the default value of the array is already SRGB, thus do nothing.
+ default:
+ break;
+ }
+ }
+ }
+ return colorSpaces;
+ }
+
+ /**
* @hide
*/
@UnsupportedAppUsage
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 209dc2cbac25..413f1a5a8955 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -24,8 +24,8 @@ import android.annotation.UiThread;
import android.content.ComponentName;
import android.content.Context;
import android.os.Handler;
-import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
import android.view.contentcapture.ContentCaptureSession.FlushReason;
@@ -52,8 +52,6 @@ public final class ContentCaptureManager {
private static final String TAG = ContentCaptureManager.class.getSimpleName();
- private static final String BG_THREAD_NAME = "intel_svc_streamer_thread";
-
/**
* Timeout for calls to system_server.
*/
@@ -90,24 +88,13 @@ public final class ContentCaptureManager {
public ContentCaptureManager(@NonNull Context context,
@Nullable IContentCaptureManager service) {
mContext = Preconditions.checkNotNull(context, "context cannot be null");
- if (VERBOSE) {
- Log.v(TAG, "Constructor for " + context.getPackageName());
- }
- mService = service;
- // TODO(b/119220549): use an existing bg thread instead...
- final HandlerThread bgThread = new HandlerThread(BG_THREAD_NAME);
- bgThread.start();
- mHandler = Handler.createAsync(bgThread.getLooper());
- }
+ if (VERBOSE) Log.v(TAG, "Constructor for " + context.getPackageName());
- @NonNull
- private static Handler newHandler() {
- // TODO(b/119220549): use an existing bg thread instead...
- // TODO(b/119220549): use UI Thread directly (as calls are one-way) or an existing bgThread
- // or a shared thread / handler held at the Application level
- final HandlerThread bgThread = new HandlerThread(BG_THREAD_NAME);
- bgThread.start();
- return Handler.createAsync(bgThread.getLooper());
+ mService = service;
+ // TODO(b/119220549): we might not even need a handler, as the IPCs are oneway. But if we
+ // do, then we should optimize it to run the tests after the Choreographer finishes the most
+ // important steps of the frame.
+ mHandler = Handler.createAsync(Looper.getMainLooper());
}
/**
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index ac13025728c2..897427fd8787 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -642,6 +642,27 @@ static jint nativeGetActiveColorMode(JNIEnv* env, jclass, jobject tokenObj) {
return static_cast<jint>(SurfaceComposerClient::getActiveColorMode(token));
}
+static jintArray nativeGetCompositionDataspaces(JNIEnv* env, jclass) {
+ ui::Dataspace defaultDataspace, wcgDataspace;
+ ui::PixelFormat defaultPixelFormat, wcgPixelFormat;
+ if (SurfaceComposerClient::getCompositionPreference(&defaultDataspace,
+ &defaultPixelFormat,
+ &wcgDataspace,
+ &wcgPixelFormat) != NO_ERROR) {
+ return nullptr;
+ }
+ jintArray array = env->NewIntArray(2);
+ if (array == nullptr) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", nullptr);
+ return nullptr;
+ }
+ jint* arrayValues = env->GetIntArrayElements(array, 0);
+ arrayValues[0] = static_cast<jint>(defaultDataspace);
+ arrayValues[1] = static_cast<jint>(wcgDataspace);
+ env->ReleaseIntArrayElements(array, arrayValues, 0);
+ return array;
+}
+
static jboolean nativeSetActiveColorMode(JNIEnv* env, jclass,
jobject tokenObj, jint colorMode) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
@@ -1020,6 +1041,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeGetActiveColorMode},
{"nativeSetActiveColorMode", "(Landroid/os/IBinder;I)Z",
(void*)nativeSetActiveColorMode},
+ {"nativeGetCompositionDataspaces", "()[I",
+ (void*)nativeGetCompositionDataspaces},
{"nativeGetHdrCapabilities", "(Landroid/os/IBinder;)Landroid/view/Display$HdrCapabilities;",
(void*)nativeGetHdrCapabilities },
{"nativeClearContentFrameStats", "(J)Z",
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index bc3e9d78affa..64fdc026cc68 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -683,6 +683,11 @@
<!-- Wifi driver supports Automatic channel selection (ACS) for softap -->
<bool translatable="false" name="config_wifi_softap_acs_supported">false</bool>
+ <!-- Channel list restriction to Automatic channel selection (ACS) for softap. If the device
+ doesn't want to restrict channels this should be empty. Value is a comma separated channel
+ string and/or channel range string like '1-6,11' -->
+ <string translatable="false" name="config_wifi_softap_acs_supported_channel_list"></string>
+
<!-- Wifi driver supports IEEE80211AC for softap -->
<bool translatable="false" name="config_wifi_softap_ieee80211ac_supported">false</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index d95c7a963ad6..9317cff054ad 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -325,6 +325,7 @@
<java-symbol type="bool" name="config_forceDefaultOrientation" />
<java-symbol type="bool" name="config_wifi_batched_scan_supported" />
<java-symbol type="bool" name="config_wifi_softap_acs_supported" />
+ <java-symbol type="string" name="config_wifi_softap_acs_supported_channel_list" />
<java-symbol type="bool" name="config_wifi_softap_ieee80211ac_supported" />
<java-symbol type="bool" name="config_enableMultiUserUI"/>
<java-symbol type="bool" name="config_enableNewAutoSelectNetworkUI"/>
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 6b9ebd3e8d12..1655e89a9b97 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -1643,10 +1643,6 @@ struct ResTable_overlayable_policy_header
// The overlay must reside of the product partition or must have existed on the product
// partition before an upgrade to overlay these resources.
POLICY_PRODUCT_PARTITION = 0x00000008,
-
- // The overlay must reside of the product services partition or must have existed on the product
- // services partition before an upgrade to overlay these resources.
- POLICY_PRODUCT_SERVICES_PARTITION = 0x00000010,
};
uint32_t policy_flags;
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index 2e386a083185..b8d3c6bf92fb 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -312,7 +312,6 @@ TEST(LoadedArscTest, LoadOverlayable) {
EXPECT_THAT(info->actor, Eq("overlay://com.android.overlayable"));
EXPECT_THAT(info->policy_flags,
Eq(ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION
- | ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION
| ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION));
info = package->GetOverlayableInfo(overlayable::R::string::overlayable4);
diff --git a/libs/androidfw/tests/data/overlayable/overlayable.apk b/libs/androidfw/tests/data/overlayable/overlayable.apk
index 863474794d00..047e6afde86b 100644
--- a/libs/androidfw/tests/data/overlayable/overlayable.apk
+++ b/libs/androidfw/tests/data/overlayable/overlayable.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml b/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml
index dba7b08628f1..fcdbe94466c1 100644
--- a/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml
+++ b/libs/androidfw/tests/data/overlayable/res/values/overlayable.xml
@@ -32,9 +32,9 @@
</overlayable>
<overlayable name="OverlayableResources2" actor="overlay://com.android.overlayable">
- <!-- Any overlay on the product_services, vendor, or product partition can overlay the value of
+ <!-- Any overlay on the vendor or product partition can overlay the value of
@string/overlayable3 -->
- <policy type="product_services|vendor|product">
+ <policy type="vendor|product">
<item type="string" name="overlayable3" />
</policy>
</overlayable>
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index 9c519963b5cb..406f9dd94bb4 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -730,7 +730,7 @@ status_t JMediaCodec::getCodecInfo(JNIEnv *env, jobject *codecInfoObject) const
CHECK(codecInfoClazz.get() != NULL);
jmethodID codecInfoCtorID = env->GetMethodID(codecInfoClazz.get(), "<init>",
- "(Ljava/lang/String;Z[Landroid/media/MediaCodecInfo$CodecCapabilities;)V");
+ "(Ljava/lang/String;Ljava/lang/String;I[Landroid/media/MediaCodecInfo$CodecCapabilities;)V");
*codecInfoObject = env->NewObject(codecInfoClazz.get(), codecInfoCtorID,
nameObject.get(), canonicalNameObject.get(), attributes, capsArrayObj.get());
diff --git a/packages/SystemUI/res-keyguard/layout/type_clock.xml b/packages/SystemUI/res-keyguard/layout/type_clock.xml
new file mode 100644
index 000000000000..21c64e9c7dbe
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/layout/type_clock.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+ -->
+<com.android.keyguard.clock.ClockLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+ <com.android.keyguard.clock.TypographicClock
+ android:id="@+id/type_clock"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ >
+ <TextView
+ android:id="@+id/header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="50dp"
+ style="@style/widget_big"
+ android:textColor="@color/typeClockAccentColor"
+ android:text="@string/type_clock_header"
+ android:textSize="40dp"
+ />
+ <TextView
+ android:id="@+id/hour"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="50dp"
+ style="@style/widget_big"
+ android:textSize="40dp"
+ />
+ <TextView
+ android:id="@+id/minute"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="50dp"
+ style="@style/widget_big"
+ android:textSize="40dp"
+ />
+ </com.android.keyguard.clock.TypographicClock>
+</com.android.keyguard.clock.ClockLayout>
diff --git a/packages/SystemUI/res-keyguard/values/colors.xml b/packages/SystemUI/res-keyguard/values/colors.xml
index 7a849ebd481d..74ee7ffad3f6 100644
--- a/packages/SystemUI/res-keyguard/values/colors.xml
+++ b/packages/SystemUI/res-keyguard/values/colors.xml
@@ -19,4 +19,6 @@
<color name="bubbleHourHandColor">#C97343</color>
<!-- Default color for minute hand of Bubble clock. -->
<color name="bubbleMinuteHandColor">#F5C983</color>
+ <!-- Accent color for Typographic clock. -->
+ <color name="typeClockAccentColor">#F5C983</color>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 1d5aa6d76991..7432f9cde639 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -402,4 +402,87 @@ number">%d</xliff:g> remaining attempt before SIM becomes permanently unusable.
number">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact carrier for details.</item>
</plurals>
+ <!-- Header for typographic clock face. [CHAR LIMIT=8] -->
+ <string name="type_clock_header">It\u2019s</string>
+
+ <!-- Hour displayed in words on the typographic clock face. [CHAR LIMIT=8] -->
+ <string-array name="type_clock_hours">
+ <item>Twelve</item>
+ <item>One</item>
+ <item>Two</item>
+ <item>Three</item>
+ <item>Four</item>
+ <item>Five</item>
+ <item>Six</item>
+ <item>Seven</item>
+ <item>Eight</item>
+ <item>Nine</item>
+ <item>Ten</item>
+ <item>Eleven</item>
+ </string-array>
+
+ <!-- Minutes displayed in words on the typographic clock face. [CHAR LIMIT=16] -->
+ <string-array name="type_clock_minutes">
+ <item>O\u2019Clock</item>
+ <item>O\u2019One</item>
+ <item>O\u2019Two</item>
+ <item>O\u2019Three</item>
+ <item>O\u2019Four</item>
+ <item>O\u2019Five</item>
+ <item>O\u2019Six</item>
+ <item>O\u2019Seven</item>
+ <item>O\u2019Eight</item>
+ <item>O\u2019Nine</item>
+ <item>Ten</item>
+ <item>Eleven</item>
+ <item>Twelve</item>
+ <item>Thirteen</item>
+ <item>Fourteen</item>
+ <item>Fifteen</item>
+ <item>Sixteen</item>
+ <item>Seventeen</item>
+ <item>Eighteen</item>
+ <item>Nineteen</item>
+ <item>Twenty</item>
+ <item>Twenty\nOne</item>
+ <item>Twenty\nTwo</item>
+ <item>Twenty\nThree</item>
+ <item>Twenty\nFour</item>
+ <item>Twenty\nFive</item>
+ <item>Twenty\nSix</item>
+ <item>Twenty\nSeven</item>
+ <item>Twenty\nEight</item>
+ <item>Twenty\nNine</item>
+ <item>Thirty</item>
+ <item>Thirty\nOne</item>
+ <item>Thirty\nTwo</item>
+ <item>Thirty\nThree</item>
+ <item>Thirty\nFour</item>
+ <item>Thirty\nFive</item>
+ <item>Thirty\nSix</item>
+ <item>Thirty\nSeven</item>
+ <item>Thirty\nEight</item>
+ <item>Thirty\nNine</item>
+ <item>Forty</item>
+ <item>Forty\nOne</item>
+ <item>Forty\nTwo</item>
+ <item>Forty\nThree</item>
+ <item>Forty\nFour</item>
+ <item>Forty\nFive</item>
+ <item>Forty\nSix</item>
+ <item>Forty\nSeven</item>
+ <item>Forty\nEight</item>
+ <item>Forty\nNine</item>
+ <item>Fifty</item>
+ <item>Fifty\nOne</item>
+ <item>Fifty\nTwo</item>
+ <item>Fifty\nThree</item>
+ <item>Fifty\nFour</item>
+ <item>Fifty\nFive</item>
+ <item>Fifty\nSix</item>
+ <item>Fifty\nSeven</item>
+ <item>Fifty\nEight</item>
+ <item>Fifty\nNine</item>
+ </string-array>
+
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index e9ce1a670fe1..1aff3949a74b 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -20,6 +20,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.keyguard.clock.BubbleClockController;
import com.android.keyguard.clock.StretchAnalogClockController;
+import com.android.keyguard.clock.TypeClockController;
import com.android.systemui.Dependency;
import com.android.systemui.plugins.ClockPlugin;
import com.android.systemui.statusbar.StatusBarState;
@@ -153,6 +154,12 @@ public class KeyguardClockSwitch extends RelativeLayout {
Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE,
StretchAnalogClockController.class.getName(),
() -> StretchAnalogClockController.build(mLayoutInflater)))
+ .withDefault(
+ new SettingsGattedSupplier(
+ mContentResolver,
+ Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE,
+ TypeClockController.class.getName(),
+ () -> TypeClockController.build(mLayoutInflater)))
.build();
mContentResolver.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE),
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
index 5aa566848732..3591dc82c8ec 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockLayout.java
@@ -36,6 +36,7 @@ public class ClockLayout extends FrameLayout {
*/
private View mDigitalClock;
private View mAnalogClock;
+ private View mTypeClock;
/**
* Pixel shifting amplitidues used to prevent screen burn-in.
@@ -60,6 +61,7 @@ public class ClockLayout extends FrameLayout {
super.onFinishInflate();
mDigitalClock = findViewById(R.id.digital_clock);
mAnalogClock = findViewById(R.id.analog_clock);
+ mTypeClock = findViewById(R.id.type_clock);
// Get pixel shifting X, Y amplitudes from resources.
Resources resources = getResources();
@@ -89,5 +91,11 @@ public class ClockLayout extends FrameLayout {
mAnalogClock.setY(Math.max(0f, 0.5f * (getHeight() - mAnalogClock.getHeight()))
+ offsetY);
}
+
+ // Put the typographic clock part way down the screen.
+ if (mTypeClock != null) {
+ mTypeClock.setX(offsetX);
+ mTypeClock.setY(0.2f * getHeight() + offsetY);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
index 91cec86392d6..8734754541a6 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/StretchAnalogClock.java
@@ -80,6 +80,7 @@ public class StretchAnalogClock extends View {
*/
public void setMinuteHandColor(int color) {
mMinutePaint.setColor(color);
+ invalidate();
}
private void init() {
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java
new file mode 100644
index 000000000000..17d929dc8a3b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/clock/TypeClockController.java
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+package com.android.keyguard.clock;
+
+import android.graphics.Paint.Style;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.android.keyguard.R;
+import com.android.systemui.plugins.ClockPlugin;
+
+import java.util.TimeZone;
+
+/**
+ * Plugin for a custom Typographic clock face that displays the time in words.
+ */
+public class TypeClockController implements ClockPlugin {
+
+ /**
+ * Custom clock shown on AOD screen and behind stack scroller on lock.
+ */
+ private View mView;
+ private TypographicClock mTypeClock;
+
+ /**
+ * Small clock shown on lock screen above stack scroller.
+ */
+ private View mLockClockContainer;
+
+ /**
+ * Controller for transition into dark state.
+ */
+ private CrossFadeDarkController mDarkController;
+
+ private TypeClockController() {}
+
+ /**
+ * Create a TypeClockController instance.
+ *
+ * @param inflater Inflater used to inflate custom clock views.
+ */
+ public static TypeClockController build(LayoutInflater inflater) {
+ TypeClockController controller = new TypeClockController();
+ controller.createViews(inflater);
+ return controller;
+ }
+
+ private void createViews(LayoutInflater inflater) {
+ mView = inflater.inflate(R.layout.type_clock, null);
+ mTypeClock = mView.findViewById(R.id.type_clock);
+
+ // For now, this view is used to hide the default digital clock.
+ // Need better transition to lock screen.
+ mLockClockContainer = inflater.inflate(R.layout.digital_clock, null);
+ mLockClockContainer.setVisibility(View.GONE);
+ }
+
+ @Override
+ public View getView() {
+ return mLockClockContainer;
+ }
+
+ @Override
+ public View getBigClockView() {
+ return mView;
+ }
+
+ @Override
+ public void setStyle(Style style) {}
+
+ @Override
+ public void setTextColor(int color) {
+ mTypeClock.setTextColor(color);
+ }
+
+ @Override
+ public void dozeTimeTick() {
+ mTypeClock.onTimeChanged();
+ }
+
+ @Override
+ public void setDarkAmount(float darkAmount) {}
+
+ @Override
+ public void onTimeZoneChanged(TimeZone timeZone) {
+ mTypeClock.onTimeZoneChanged(timeZone);
+ }
+
+ @Override
+ public boolean shouldShowStatusArea() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java
new file mode 100644
index 000000000000..5f9da3ee33bb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/keyguard/clock/TypographicClock.java
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+package com.android.keyguard.clock;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.text.format.DateFormat;
+import android.util.AttributeSet;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.keyguard.R;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+/**
+ * Clock that presents the time in words.
+ */
+public class TypographicClock extends LinearLayout {
+
+ private final String[] mHours;
+ private final String[] mMinutes;
+ private TextView mHeaderText;
+ private TextView mHourText;
+ private TextView mMinuteText;
+ private Calendar mTime;
+ private String mDescFormat;
+ private TimeZone mTimeZone;
+
+ public TypographicClock(Context context) {
+ this(context, null);
+ }
+
+ public TypographicClock(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public TypographicClock(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mTime = Calendar.getInstance();
+ mDescFormat = ((SimpleDateFormat) DateFormat.getTimeFormat(context)).toLocalizedPattern();
+ Resources res = context.getResources();
+ mHours = res.getStringArray(R.array.type_clock_hours);
+ mMinutes = res.getStringArray(R.array.type_clock_minutes);
+ }
+
+ /**
+ * Call when the time changes to update the text of the time.
+ */
+ public void onTimeChanged() {
+ mTime.setTimeInMillis(System.currentTimeMillis());
+ setContentDescription(DateFormat.format(mDescFormat, mTime));
+ final int hour = mTime.get(Calendar.HOUR);
+ mHourText.setText(mHours[hour % 12]);
+ final int minute = mTime.get(Calendar.MINUTE);
+ mMinuteText.setText(mMinutes[minute % 60]);
+ invalidate();
+ }
+
+ /**
+ * Call when the time zone has changed to update clock time.
+ *
+ * @param timeZone The updated time zone that will be used.
+ */
+ public void onTimeZoneChanged(TimeZone timeZone) {
+ mTimeZone = timeZone;
+ mTime.setTimeZone(timeZone);
+ }
+
+ /**
+ * Set the color of the text used to display the time.
+ *
+ * This is necessary when the wallpaper shown behind the clock on the
+ * lock screen changes.
+ */
+ public void setTextColor(int color) {
+ mHourText.setTextColor(color);
+ mMinuteText.setTextColor(color);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mHeaderText = findViewById(R.id.header);
+ mHourText = findViewById(R.id.hour);
+ mMinuteText = findViewById(R.id.minute);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mTime = Calendar.getInstance(mTimeZone != null ? mTimeZone : TimeZone.getDefault());
+ onTimeChanged();
+ }
+}
diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java
index 16143d3ae9e0..74fbea1544bd 100644
--- a/services/core/java/com/android/server/om/IdmapManager.java
+++ b/services/core/java/com/android/server/om/IdmapManager.java
@@ -24,11 +24,14 @@ import static com.android.server.om.OverlayManagerService.TAG;
import android.annotation.NonNull;
import android.content.om.OverlayInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
+import android.os.Build.VERSION_CODES;
import android.os.IBinder;
import android.os.IIdmap2;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.Slog;
@@ -51,6 +54,13 @@ class IdmapManager {
private final Installer mInstaller;
private IIdmap2 mIdmap2Service;
+ private static final boolean VENDOR_IS_Q_OR_LATER;
+ static {
+ // STOPSHIP(b/119390857): Check api version once Q sdk version is finalized
+ final String value = SystemProperties.get("ro.vndk.version", "Q");
+ VENDOR_IS_Q_OR_LATER = value.equals("Q") || value.equals("q");
+ }
+
IdmapManager(final Installer installer) {
mInstaller = installer;
if (FEATURE_FLAG_IDMAP2) {
@@ -69,10 +79,13 @@ class IdmapManager {
final String overlayPath = overlayPackage.applicationInfo.getBaseCodePath();
try {
if (FEATURE_FLAG_IDMAP2) {
- if (mIdmap2Service.verifyIdmap(overlayPath, userId)) {
+ int policies = determineFulfilledPolicies(overlayPackage);
+ boolean enforce = enforceOverlayable(overlayPackage);
+ if (mIdmap2Service.verifyIdmap(overlayPath, policies, enforce, userId)) {
return true;
}
- return mIdmap2Service.createIdmap(targetPath, overlayPath, userId) != null;
+ return mIdmap2Service.createIdmap(targetPath, overlayPath, policies, enforce,
+ userId) != null;
} else {
mInstaller.idmap(targetPath, overlayPath, sharedGid);
return true;
@@ -156,4 +169,71 @@ class IdmapManager {
}, SECOND_IN_MILLIS);
}
}
+
+ /**
+ * Checks if overlayable and policies should be enforced on the specified overlay for backwards
+ * compatibility with pre-Q overlays.
+ */
+ private boolean enforceOverlayable(@NonNull final PackageInfo overlayPackage) {
+ final ApplicationInfo ai = overlayPackage.applicationInfo;
+ if (ai.targetSdkVersion >= VERSION_CODES.Q) {
+ // Always enforce policies for overlays targeting Q+.
+ return true;
+ }
+
+ if (ai.isVendor() && !VENDOR_IS_Q_OR_LATER) {
+ // If the overlay is on a pre-Q vendor partition, do not enforce overlayable
+ // restrictions on this overlay because the pre-Q platform has no understanding of
+ // overlayable.
+ return false;
+ }
+
+ // Do not enforce overlayable restrictions on pre-Q overlays signed with the
+ // platform signature.
+ return !ai.isSignedWithPlatformKey();
+ }
+
+ /**
+ * Retrieves a bitmask for idmap2 that represents the policies the specified overlay fulfills.
+ * @throws SecurityException if the overlay is not allowed to overlay any resource
+ */
+ private int determineFulfilledPolicies(@NonNull final PackageInfo overlayPackage)
+ throws SecurityException {
+ final ApplicationInfo ai = overlayPackage.applicationInfo;
+ final boolean overlayIsQOrLater = ai.targetSdkVersion >= VERSION_CODES.Q;
+
+ int fulfilledPolicies = 0;
+
+ // TODO(b/119402606) : Add signature policy
+
+ // Vendor partition (/vendor)
+ if (ai.isVendor()) {
+ if (overlayIsQOrLater) {
+ fulfilledPolicies |= IIdmap2.POLICY_VENDOR_PARTITION;
+ } else if (VENDOR_IS_Q_OR_LATER) {
+ throw new SecurityException("Overlay must target Q sdk or higher");
+ }
+ }
+
+ // Product partition (/product)
+ if (ai.isProduct()) {
+ if (overlayIsQOrLater) {
+ fulfilledPolicies |= IIdmap2.POLICY_PRODUCT_PARTITION;
+ } else {
+ throw new SecurityException("Overlay must target Q sdk or higher");
+ }
+ }
+
+ // System partition (/system)
+ if (ai.isSystemApp()) {
+ if (overlayIsQOrLater) {
+ fulfilledPolicies |= IIdmap2.POLICY_SYSTEM_PARTITION;
+ } else {
+ throw new SecurityException("Overlay must target Q sdk or higher");
+ }
+ }
+
+ // All overlays can overlay resources with the public policy
+ return fulfilledPolicies | IIdmap2.POLICY_PUBLIC;
+ }
}
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index b0d2704196a6..1cbf0bfac05c 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -270,7 +270,9 @@ final class OverlayManagerServiceImpl {
Slog.d(TAG, "onTargetPackageUpgraded packageName=" + packageName + " userId=" + userId);
}
- updateAllOverlaysForTarget(packageName, userId, 0);
+ if (updateAllOverlaysForTarget(packageName, userId, 0)) {
+ mListener.onOverlaysChanged(packageName, userId);
+ }
}
void onTargetPackageRemoved(@NonNull final String packageName, final int userId) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 249d55a5d5ca..6fe32c5677d4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1343,6 +1343,7 @@ public class PackageManagerService extends IPackageManager.Stub
final @Nullable String mWellbeingPackage;
final @Nullable String mDocumenterPackage;
final @Nullable String mConfiguratorPackage;
+ final @Nullable String mAppPredictionServicePackage;
final @NonNull String mServicesSystemSharedLibraryPackageName;
final @NonNull String mSharedSystemSharedLibraryPackageName;
@@ -2868,6 +2869,7 @@ public class PackageManagerService extends IPackageManager.Stub
mDocumenterPackage = getDocumenterPackageName();
mConfiguratorPackage =
mContext.getString(R.string.config_deviceConfiguratorPackageName);
+ mAppPredictionServicePackage = getAppPredictionServicePackageName();
// Now that we know all of the shared libraries, update all clients to have
// the correct library paths.
@@ -3750,7 +3752,7 @@ public class PackageManagerService extends IPackageManager.Stub
/**
* Returns whether or not a full application can see an instant application.
* <p>
- * Currently, there are three cases in which this can occur:
+ * Currently, there are four cases in which this can occur:
* <ol>
* <li>The calling application is a "special" process. Special processes
* are those with a UID < {@link Process#FIRST_APPLICATION_UID}.</li>
@@ -3758,6 +3760,7 @@ public class PackageManagerService extends IPackageManager.Stub
* {@link android.Manifest.permission#ACCESS_INSTANT_APPS}.</li>
* <li>The calling application is the default launcher on the
* system partition.</li>
+ * <li>The calling application is the default app prediction service.</li>
* </ol>
*/
private boolean canViewInstantApps(int callingUid, int userId) {
@@ -3775,6 +3778,11 @@ public class PackageManagerService extends IPackageManager.Stub
&& isCallerSameApp(homeComponent.getPackageName(), callingUid)) {
return true;
}
+ // TODO(b/122900055) Change/Remove this and replace with new permission role.
+ if (mAppPredictionServicePackage != null
+ && isCallerSameApp(mAppPredictionServicePackage, callingUid)) {
+ return true;
+ }
}
return false;
}
@@ -19820,6 +19828,14 @@ public class PackageManagerService extends IPackageManager.Stub
.setPackage(launcherComponent.getPackageName());
mContext.sendBroadcastAsUser(launcherIntent, UserHandle.of(launcherUid));
}
+ // TODO(b/122900055) Change/Remove this and replace with new permission role.
+ if (mAppPredictionServicePackage != null) {
+ Intent predictorIntent = new Intent(PackageInstaller.ACTION_SESSION_COMMITTED)
+ .putExtra(PackageInstaller.EXTRA_SESSION, sessionInfo)
+ .putExtra(Intent.EXTRA_USER, UserHandle.of(userId))
+ .setPackage(mAppPredictionServicePackage);
+ mContext.sendBroadcastAsUser(predictorIntent, UserHandle.of(launcherUid));
+ }
}
}
@@ -19972,6 +19988,20 @@ public class PackageManagerService extends IPackageManager.Stub
return mContext.getString(R.string.config_defaultWellbeingPackage);
}
+ private String getAppPredictionServicePackageName() {
+ String flattenedAppPredictionServiceComponentName =
+ mContext.getString(R.string.config_defaultAppPredictionService);
+ if (flattenedAppPredictionServiceComponentName == null) {
+ return null;
+ }
+ ComponentName appPredictionServiceComponentName =
+ ComponentName.unflattenFromString(flattenedAppPredictionServiceComponentName);
+ if (appPredictionServiceComponentName == null) {
+ return null;
+ }
+ return appPredictionServiceComponentName.getPackageName();
+ }
+
@Override
public void setApplicationEnabledSetting(String appPackageName,
int newState, int flags, int userId, String callingPackage) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 1f5c64e92ac0..bc1f7981258d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -42,6 +42,7 @@ import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.IUidObserver;
+import android.app.Person;
import android.app.usage.UsageStatsManagerInternal;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
@@ -1588,6 +1589,14 @@ public abstract class BaseShortcutManagerTest extends InstrumentationTestCase {
}
/**
+ * Make a Person.
+ */
+ protected Person makePerson(CharSequence name, String key, String uri) {
+ final Person.Builder builder = new Person.Builder();
+ return builder.setName(name).setKey(key).setUri(uri).build();
+ }
+
+ /**
* Make an component name, with the client context.
*/
@NonNull
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 9b59f9151fd0..8d0365b534b5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -248,6 +248,8 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setRank(123)
+ .setPerson(makePerson("person", "personKey", "personUri"))
+ .setLongLived()
.setExtras(pb)
.build();
si.addFlags(ShortcutInfo.FLAG_PINNED);
@@ -267,9 +269,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
+ assertEquals("person", si.getPersons()[0].getName());
+ assertEquals("personKey", si.getPersons()[0].getKey());
+ assertEquals("personUri", si.getPersons()[0].getUri());
assertEquals(1, si.getExtras().getInt("k"));
- assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
+ assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
assertEquals("abc", si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
@@ -345,6 +350,8 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
.setCategories(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"))
.setIntent(makeIntent("action", ShortcutActivity.class, "key", "val"))
.setRank(123)
+ .setPerson(makePerson("person", "personKey", "personUri"))
+ .setLongLived()
.setExtras(pb)
.build();
sorig.addFlags(ShortcutInfo.FLAG_PINNED);
@@ -368,9 +375,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
+ assertEquals("person", si.getPersons()[0].getName());
+ assertEquals("personKey", si.getPersons()[0].getKey());
+ assertEquals("personUri", si.getPersons()[0].getUri());
assertEquals(1, si.getExtras().getInt("k"));
- assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
+ assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
assertEquals("abc", si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
assertEquals("string/r456", si.getIconResName());
@@ -388,9 +398,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals("action", si.getIntent().getAction());
assertEquals("val", si.getIntent().getStringExtra("key"));
assertEquals(123, si.getRank());
+ assertEquals("person", si.getPersons()[0].getName());
+ assertEquals("personKey", si.getPersons()[0].getKey());
+ assertEquals("personUri", si.getPersons()[0].getUri());
assertEquals(1, si.getExtras().getInt("k"));
- assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
+ assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
assertEquals(null, si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
@@ -408,9 +421,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals(null, si.getIntent());
assertEquals(123, si.getRank());
+ assertEquals("person", si.getPersons()[0].getName());
+ assertEquals("personKey", si.getPersons()[0].getKey());
+ assertEquals("personUri", si.getPersons()[0].getUri());
assertEquals(1, si.getExtras().getInt("k"));
- assertEquals(ShortcutInfo.FLAG_PINNED, si.getFlags());
+ assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
assertEquals(null, si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
@@ -428,9 +444,11 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(null, si.getCategories());
assertEquals(null, si.getIntent());
assertEquals(0, si.getRank());
+ assertEquals(null, si.getPersons());
assertEquals(null, si.getExtras());
- assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY, si.getFlags());
+ assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_KEY_FIELDS_ONLY
+ | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
assertEquals(null, si.getBitmapPath());
assertEquals(456, si.getIconResourceId());
@@ -692,6 +710,12 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
si = sorig.clone(/* flags=*/ 0);
si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
+ .setPerson(makePerson("person", "", "")).build());
+ assertEquals("text", si.getText());
+ assertEquals("person", si.getPersons()[0].getName());
+
+ si = sorig.clone(/* flags=*/ 0);
+ si.copyNonNullFieldsFrom(new ShortcutInfo.Builder(getTestContext()).setId("id")
.setIntent(makeIntent("action2", ShortcutActivity.class)).build());
assertEquals("text", si.getText());
assertEquals("action2", si.getIntent().getAction());
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index c81670139eae..9fee5932dadc 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -805,9 +805,11 @@ public class PhoneStateListener {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
- Binder.withCleanCallingIdentity(
- () -> mExecutor.execute(
- () -> psl.onDataConnectionStateChanged(state, networkType)));
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(
+ () -> {
+ psl.onDataConnectionStateChanged(state, networkType);
+ psl.onDataConnectionStateChanged(state);
+ }));
}
public void onDataActivity(int direction) {
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index e2350fe78500..9414abd98b1c 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -92,7 +92,7 @@ public class ImsMmTelManager {
public static final int WIFI_MODE_WIFI_PREFERRED = 2;
/**
- * Callback class for receiving Registration callback events.
+ * Callback class for receiving IMS network Registration callback events.
* @see #registerImsRegistrationCallback(Executor, RegistrationCallback) (RegistrationCallback)
* @see #unregisterImsRegistrationCallback(RegistrationCallback)
*/
@@ -241,7 +241,8 @@ public class ImsMmTelManager {
}
/**
- * Receives IMS capability status updates from the ImsService.
+ * Receives IMS capability status updates from the ImsService. This information is also
+ * available via the {@link #isAvailable(int, int)} method below.
*
* @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback) (CapabilityCallback)
* @see #unregisterMmTelCapabilityCallback(CapabilityCallback)
@@ -290,6 +291,8 @@ public class ImsMmTelManager {
* If unavailable, the feature is not able to support the unavailable capability at this
* time.
*
+ * This information can also be queried using the {@link #isAvailable(int, int)} API.
+ *
* @param capabilities The new availability of the capabilities.
*/
public void onCapabilitiesStatusChanged(
@@ -304,7 +307,7 @@ public class ImsMmTelManager {
/**@hide*/
// Only exposed as public method for compatibility with deprecated ImsManager APIs.
// TODO: clean up dependencies and change back to private visibility.
- public void setExecutor(Executor executor) {
+ public final void setExecutor(Executor executor) {
mBinder.setExecutor(executor);
}
}
@@ -342,8 +345,7 @@ public class ImsMmTelManager {
* Registers a {@link RegistrationCallback} with the system, which will provide registration
* updates for the subscription specified in {@link #createForSubscriptionId(Context, int)}. Use
* {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed
- * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up
- * after a subscription is removed.
+ * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up.
*
* When the callback is registered, it will initiate the callback c to be called with the
* current registration state.
@@ -351,6 +353,12 @@ public class ImsMmTelManager {
* @param executor The executor the callback events should be run on.
* @param c The {@link RegistrationCallback} to be added.
* @see #unregisterImsRegistrationCallback(RegistrationCallback)
+ * @throws IllegalArgumentException if the subscription associated with this callback is not
+ * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or
+ * {@link CapabilityCallback} callback.
+ * @throws IllegalStateException if the subscription associated with this callback is valid, but
+ * the {@link ImsService} associated with the subscription is not available. This can happen if
+ * the service crashed, for example.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void registerImsRegistrationCallback(@CallbackExecutor Executor executor,
@@ -370,11 +378,17 @@ public class ImsMmTelManager {
}
/**
- * Removes an existing {@link RegistrationCallback}. Ensure to call this method when cleaning
- * up to avoid memory leaks or when the subscription is removed.
+ * Removes an existing {@link RegistrationCallback}.
+ *
+ * When the subscription associated with this callback is removed (SIM removed, ESIM swap,
+ * etc...), this callback will automatically be removed. If this method is called for an
+ * inactive subscription, it will result in a no-op.
+ *
* @param c The {@link RegistrationCallback} to be removed.
* @see SubscriptionManager.OnSubscriptionsChangedListener
* @see #registerImsRegistrationCallback(Executor, RegistrationCallback)
+ * @throws IllegalArgumentException if the subscription ID associated with this callback is
+ * invalid.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c) {
@@ -389,12 +403,14 @@ public class ImsMmTelManager {
}
/**
- * Registers a {@link CapabilityCallback} with the system, which will provide MmTel capability
- * updates for the subscription specified in {@link #createForSubscriptionId(Context, int)}.
+ * Registers a {@link CapabilityCallback} with the system, which will provide MmTel service
+ * availability updates for the subscription specified in
+ * {@link #createForSubscriptionId(Context, int)}. The method {@link #isAvailable(int, int)}
+ * can also be used to query this information at any time.
+ *
* Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
* subscription changed events and call
- * {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up after a
- * subscription is removed.
+ * {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up.
*
* When the callback is registered, it will initiate the callback c to be called with the
* current capabilities.
@@ -402,9 +418,15 @@ public class ImsMmTelManager {
* @param executor The executor the callback events should be run on.
* @param c The MmTel {@link CapabilityCallback} to be registered.
* @see #unregisterMmTelCapabilityCallback(CapabilityCallback)
+ * @throws IllegalArgumentException if the subscription associated with this callback is not
+ * active (SIM is not inserted, ESIM inactive) or invalid, or a null {@link Executor} or
+ * {@link CapabilityCallback} callback.
+ * @throws IllegalStateException if the subscription associated with this callback is valid, but
+ * the {@link ImsService} associated with the subscription is not available. This can happen if
+ * the service crashed, for example.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void registerMmTelCapabilityCallback(@CallbackExecutor Executor executor,
+ public void registerMmTelCapabilityCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull CapabilityCallback c) {
if (c == null) {
throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
@@ -421,10 +443,15 @@ public class ImsMmTelManager {
}
/**
- * Removes an existing MmTel {@link CapabilityCallback}. Be sure to call this when cleaning
- * up to avoid memory leaks.
+ * Removes an existing MmTel {@link CapabilityCallback}.
+ *
+ * When the subscription associated with this callback is removed (SIM removed, ESIM swap,
+ * etc...), this callback will automatically be removed. If this method is called for an
+ * inactive subscription, it will result in a no-op.
* @param c The MmTel {@link CapabilityCallback} to be removed.
* @see #registerMmTelCapabilityCallback(Executor, CapabilityCallback)
+ * @throws IllegalArgumentException if the subscription ID associated with this callback is
+ * invalid.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void unregisterMmTelCapabilityCallback(@NonNull CapabilityCallback c) {
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 916e282f642e..d37198a3e25d 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -133,33 +133,40 @@ public class ProvisioningManager {
}
/**
- * Register a new {@link Callback} to listen to changes to changes in
- * IMS provisioning. Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
- * Subscription changed events and call
- * {@link #unregisterProvisioningChangedCallback(Callback)} to clean up after a
- * subscription is removed.
+ * Register a new {@link Callback} to listen to changes to changes in IMS provisioning.
+ *
+ * When the subscription associated with this callback is removed (SIM removed, ESIM swap,
+ * etc...), this callback will automatically be removed.
* @param executor The {@link Executor} to call the callback methods on
* @param callback The provisioning callbackto be registered.
* @see #unregisterProvisioningChangedCallback(Callback)
* @see SubscriptionManager.OnSubscriptionsChangedListener
+ * @throws IllegalArgumentException if the subscription associated with this callback is not
+ * active (SIM is not inserted, ESIM inactive) or the subscription is invalid.
+ * @throws IllegalStateException if the subscription associated with this callback is valid, but
+ * the {@link ImsService} associated with the subscription is not available. This can happen if
+ * the service crashed, for example.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void registerProvisioningChangedCallback(@CallbackExecutor Executor executor,
@NonNull Callback callback) {
callback.setExecutor(executor);
try {
- getITelephony().registerImsProvisioningChangedCallback(mSubId,
- callback.getBinder());
+ getITelephony().registerImsProvisioningChangedCallback(mSubId, callback.getBinder());
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
}
}
/**
- * Unregister an existing {@link Callback}. Ensure to call this method when cleaning
- * up to avoid memory leaks or when the subscription is removed.
+ * Unregister an existing {@link Callback}. When the subscription associated with this
+ * callback is removed (SIM removed, ESIM swap, etc...), this callback will automatically be
+ * removed. If this method is called for an inactive subscription, it will result in a no-op.
* @param callback The existing {@link Callback} to be removed.
* @see #registerProvisioningChangedCallback(Executor, Callback)
+ *
+ * @throws IllegalArgumentException if the subscription associated with this callback is
+ * invalid.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void unregisterProvisioningChangedCallback(@NonNull Callback callback) {
diff --git a/tests/ActivityViewTest/AndroidManifest.xml b/tests/ActivityViewTest/AndroidManifest.xml
index 0be1ea0fdfd2..17eb029166f0 100644
--- a/tests/ActivityViewTest/AndroidManifest.xml
+++ b/tests/ActivityViewTest/AndroidManifest.xml
@@ -57,5 +57,10 @@
android:exported="true"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density">
</activity>
+
+ <activity android:name=".ActivityViewVisibilityActivity"
+ android:label="AV Visibility"
+ android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|colorMode|density">
+ </activity>
</application>
</manifest>
diff --git a/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml
index ba2e91166440..efcaef679a9c 100644
--- a/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml
+++ b/tests/ActivityViewTest/res/layout/activity_view_main_activity.xml
@@ -41,4 +41,10 @@
android:text="Test Resize ActivityView"
android:textAllCaps="false"/>
+ <Button
+ android:id="@+id/visibility_activity_view_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Test ActivityView Visibility"
+ android:textAllCaps="false"/>
</LinearLayout>
diff --git a/tests/ActivityViewTest/res/layout/activity_view_visibility_activity.xml b/tests/ActivityViewTest/res/layout/activity_view_visibility_activity.xml
new file mode 100644
index 000000000000..d29d4dfc0428
--- /dev/null
+++ b/tests/ActivityViewTest/res/layout/activity_view_visibility_activity.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#cfd8dc">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+
+ <Button
+ android:id="@+id/activity_launch_button"
+ android:layout_width="200dp"
+ android:layout_height="wrap_content"
+ android:text="Launch test activity" />
+
+ <Spinner
+ android:id="@+id/visibility_spinner"
+ android:layout_width="200dp"
+ android:layout_height="match_parent"/>
+
+ </LinearLayout>
+
+ <ActivityView
+ android:id="@+id/activity_view"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+</LinearLayout>
diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java
index 66f0c6a56afd..4f09c28fe711 100644
--- a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java
+++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewMainActivity.java
@@ -35,5 +35,8 @@ public class ActivityViewMainActivity extends Activity {
findViewById(R.id.resize_activity_view_button).setOnClickListener(
v -> startActivity(new Intent(this, ActivityViewResizeActivity.class)));
+
+ findViewById(R.id.visibility_activity_view_button).setOnClickListener(
+ v -> startActivity(new Intent(this, ActivityViewVisibilityActivity.class)));
}
}
diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java
index ba2c764bd7d7..52aba2b13c42 100644
--- a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java
+++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewTestActivity.java
@@ -24,12 +24,14 @@ import static android.view.MotionEvent.ACTION_UP;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.TextView;
public class ActivityViewTestActivity extends Activity {
+ private static final String TAG = "ActivityViewTestActivity";
private View mRoot;
private TextView mTextView;
@@ -84,6 +86,7 @@ public class ActivityViewTestActivity extends Activity {
}
private void updateStateText(String state) {
+ Log.d(TAG, state);
mTextView.setText(state);
}
diff --git a/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewVisibilityActivity.java b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewVisibilityActivity.java
new file mode 100644
index 000000000000..ecd2cf3c578e
--- /dev/null
+++ b/tests/ActivityViewTest/src/com/google/android/test/activityview/ActivityViewVisibilityActivity.java
@@ -0,0 +1,75 @@
+/**
+ * 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.
+ */
+
+package com.google.android.test.activityview;
+
+import static android.view.View.GONE;
+import static android.view.View.INVISIBLE;
+import static android.view.View.VISIBLE;
+
+import android.app.Activity;
+import android.app.ActivityView;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.Spinner;
+
+public class ActivityViewVisibilityActivity extends Activity {
+ private static final String[] sVisibilityOptions = {"VISIBLE", "INVISIBLE", "GONE"};
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_view_visibility_activity);
+
+ final ActivityView activityView = findViewById(R.id.activity_view);
+ final Button launchButton = findViewById(R.id.activity_launch_button);
+ launchButton.setOnClickListener(v -> {
+ final Intent intent = new Intent(this, ActivityViewTestActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+ activityView.startActivity(intent);
+ });
+
+ final Spinner visibilitySpinner = findViewById(R.id.visibility_spinner);
+ final ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
+ android.R.layout.simple_spinner_item, sVisibilityOptions);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ visibilitySpinner.setAdapter(adapter);
+ visibilitySpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ switch (position) {
+ case 0:
+ activityView.setVisibility(VISIBLE);
+ break;
+ case 1:
+ activityView.setVisibility(INVISIBLE);
+ break;
+ case 2:
+ activityView.setVisibility(GONE);
+ break;
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ });
+ }
+}
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 58702dc465cc..e0d2f48e8dcf 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -1164,8 +1164,6 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
current_policies |= OverlayableItem::Policy::kPublic;
} else if (trimmed_part == "product") {
current_policies |= OverlayableItem::Policy::kProduct;
- } else if (trimmed_part == "product_services") {
- current_policies |= OverlayableItem::Policy::kProductServices;
} else if (trimmed_part == "system") {
current_policies |= OverlayableItem::Policy::kSystem;
} else if (trimmed_part == "vendor") {
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index debca9c1e1ba..827c7deaf452 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -935,9 +935,6 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
<policy type="product">
<item type="string" name="bar" />
</policy>
- <policy type="product_services">
- <item type="string" name="baz" />
- </policy>
<policy type="system">
<item type="string" name="fiz" />
</policy>
@@ -966,14 +963,6 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct));
- search_result = table_.FindResource(test::ParseNameOrDie("string/baz"));
- ASSERT_TRUE(search_result);
- ASSERT_THAT(search_result.value().entry, NotNull());
- ASSERT_TRUE(search_result.value().entry->overlayable_item);
- result_overlayable_item = search_result.value().entry->overlayable_item.value();
- EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
- EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProductServices));
-
search_result = table_.FindResource(test::ParseNameOrDie("string/fiz"));
ASSERT_TRUE(search_result);
ASSERT_THAT(search_result.value().entry, NotNull());
@@ -1028,7 +1017,7 @@ TEST_F(ResourceParserTest, ParseOverlayableBadPolicyError) {
TEST_F(ResourceParserTest, ParseOverlayableMultiplePolicy) {
std::string input = R"(
<overlayable name="Name">
- <policy type="vendor|product_services">
+ <policy type="vendor|public">
<item type="string" name="foo" />
</policy>
<policy type="product|system">
@@ -1044,7 +1033,7 @@ TEST_F(ResourceParserTest, ParseOverlayableMultiplePolicy) {
OverlayableItem result_overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kVendor
- | OverlayableItem::Policy::kProductServices));
+ | OverlayableItem::Policy::kPublic));
search_result = table_.FindResource(test::ParseNameOrDie("string/bar"));
ASSERT_TRUE(search_result);
@@ -1139,7 +1128,7 @@ TEST_F(ResourceParserTest, NestPolicyInOverlayableError) {
std::string input = R"(
<overlayable name="Name">
<policy type="vendor|product">
- <policy type="product_services">
+ <policy type="public">
<item type="string" name="foo" />
</policy>
</policy>
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index eaf6a47a15fd..7ca99ea42b50 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -92,9 +92,6 @@ struct OverlayableItem {
// The resource can be overlaid by any overlay on the product partition.
kProduct = 0x08,
-
- // The resource can be overlaid by any overlay on the product services partition.
- kProductServices = 0x10
};
std::shared_ptr<Overlayable> overlayable;
diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp
index a733134f123c..b97dc6b205ca 100644
--- a/tools/aapt2/ResourceTable_test.cpp
+++ b/tools/aapt2/ResourceTable_test.cpp
@@ -248,7 +248,7 @@ TEST(ResourceTableTest, SetOverlayable) {
Source("res/values/overlayable.xml", 40));
OverlayableItem overlayable_item(overlayable);
overlayable_item.policies |= OverlayableItem::Policy::kProduct;
- overlayable_item.policies |= OverlayableItem::Policy::kProductServices;
+ overlayable_item.policies |= OverlayableItem::Policy::kVendor;
overlayable_item.comment = "comment";
overlayable_item.source = Source("res/values/overlayable.xml", 42);
@@ -265,7 +265,7 @@ TEST(ResourceTableTest, SetOverlayable) {
EXPECT_THAT(result_overlayable_item.overlayable->source.path, Eq("res/values/overlayable.xml"));
EXPECT_THAT(result_overlayable_item.overlayable->source.line, 40);
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct
- | OverlayableItem::Policy::kProductServices));
+ | OverlayableItem::Policy::kVendor));
ASSERT_THAT(result_overlayable_item.comment, StrEq("comment"));
EXPECT_THAT(result_overlayable_item.source.path, Eq("res/values/overlayable.xml"));
EXPECT_THAT(result_overlayable_item.source.line, 42);
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
index da541be9502b..73b568e77689 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -155,7 +155,6 @@ message OverlayableItem {
SYSTEM = 1;
VENDOR = 2;
PRODUCT = 3;
- PRODUCT_SERVICES = 4;
}
// The location of the <item> declaration in source.
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp
index 7d4c6f348403..40aaa05c2b30 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.cpp
+++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp
@@ -473,10 +473,6 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) {
& ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION) {
policies |= OverlayableItem::Policy::kProduct;
}
- if (policy_header->policy_flags
- & ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION) {
- policies |= OverlayableItem::Policy::kProductServices;
- }
const ResTable_ref* const ref_begin = reinterpret_cast<const ResTable_ref*>(
((uint8_t *)policy_header) + util::DeviceToHost32(policy_header->header.headerSize));
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index c4ecbafc008b..9d341cc1ca4a 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -485,9 +485,6 @@ class PackageFlattener {
if (item.policies & OverlayableItem::Policy::kProduct) {
policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION;
}
- if (item.policies & OverlayableItem::Policy::kProductServices) {
- policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION;
- }
}
auto policy = overlayable_chunk->policy_ids.find(policy_flags);
diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp
index 18fecf60c977..ddc117399390 100644
--- a/tools/aapt2/format/binary/TableFlattener_test.cpp
+++ b/tools/aapt2/format/binary/TableFlattener_test.cpp
@@ -660,12 +660,10 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) {
OverlayableItem overlayable_item_zero(overlayable);
overlayable_item_zero.policies |= OverlayableItem::Policy::kProduct;
overlayable_item_zero.policies |= OverlayableItem::Policy::kSystem;
- overlayable_item_zero.policies |= OverlayableItem::Policy::kProductServices;
std::string name_one = "com.app.test:integer/overlayable_one_item";
OverlayableItem overlayable_item_one(overlayable);
overlayable_item_one.policies |= OverlayableItem::Policy::kPublic;
- overlayable_item_one.policies |= OverlayableItem::Policy::kProductServices;
std::string name_two = "com.app.test:integer/overlayable_two_item";
OverlayableItem overlayable_item_two(overlayable);
@@ -698,16 +696,14 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) {
ASSERT_TRUE(search_result.value().entry->overlayable_item);
OverlayableItem& overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kSystem
- | OverlayableItem::Policy::kProduct
- | OverlayableItem::Policy::kProductServices);
+ | OverlayableItem::Policy::kProduct);
search_result = output_table.FindResource(test::ParseNameOrDie(name_one));
ASSERT_TRUE(search_result);
ASSERT_THAT(search_result.value().entry, NotNull());
ASSERT_TRUE(search_result.value().entry->overlayable_item);
overlayable_item = search_result.value().entry->overlayable_item.value();
- EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic
- | OverlayableItem::Policy::kProductServices);
+ EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic);
search_result = output_table.FindResource(test::ParseNameOrDie(name_two));
ASSERT_TRUE(search_result);
@@ -735,13 +731,11 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
OverlayableItem overlayable_item_zero(group);
overlayable_item_zero.policies |= OverlayableItem::Policy::kProduct;
overlayable_item_zero.policies |= OverlayableItem::Policy::kSystem;
- overlayable_item_zero.policies |= OverlayableItem::Policy::kProductServices;
auto group_one = std::make_shared<Overlayable>("OtherName", "overlay://customization");
std::string name_one = "com.app.test:integer/overlayable_one";
OverlayableItem overlayable_item_one(group_one);
overlayable_item_one.policies |= OverlayableItem::Policy::kPublic;
- overlayable_item_one.policies |= OverlayableItem::Policy::kProductServices;
std::string name_two = "com.app.test:integer/overlayable_two";
OverlayableItem overlayable_item_two(group);
@@ -773,8 +767,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
EXPECT_EQ(result_overlayable.overlayable->name, "TestName");
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://theme");
EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSystem
- | OverlayableItem::Policy::kProduct
- | OverlayableItem::Policy::kProductServices);
+ | OverlayableItem::Policy::kProduct);
search_result = output_table.FindResource(test::ParseNameOrDie(name_one));
ASSERT_TRUE(search_result);
ASSERT_THAT(search_result.value().entry, NotNull());
@@ -782,8 +775,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
result_overlayable = search_result.value().entry->overlayable_item.value();
EXPECT_EQ(result_overlayable.overlayable->name, "OtherName");
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization");
- EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kPublic
- | OverlayableItem::Policy::kProductServices);
+ EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kPublic);
search_result = output_table.FindResource(test::ParseNameOrDie(name_two));
ASSERT_TRUE(search_result);
ASSERT_THAT(search_result.value().entry, NotNull());
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index 6b5746d63bf8..aff1b391f861 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -390,9 +390,6 @@ bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable,
case pb::OverlayableItem::PRODUCT:
out_overlayable->policies |= OverlayableItem::Policy::kProduct;
break;
- case pb::OverlayableItem::PRODUCT_SERVICES:
- out_overlayable->policies |= OverlayableItem::Policy::kProductServices;
- break;
default:
*out_error = "unknown overlayable policy";
return false;
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index 76fbb464b62a..b549e2369f98 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -303,9 +303,6 @@ static void SerializeOverlayableItemToPb(const OverlayableItem& overlayable_item
if (overlayable_item.policies & OverlayableItem::Policy::kProduct) {
pb_overlayable_item->add_policy(pb::OverlayableItem::PRODUCT);
}
- if (overlayable_item.policies & OverlayableItem::Policy::kProductServices) {
- pb_overlayable_item->add_policy(pb::OverlayableItem::PRODUCT_SERVICES);
- }
if (overlayable_item.policies & OverlayableItem::Policy::kSystem) {
pb_overlayable_item->add_policy(pb::OverlayableItem::SYSTEM);
}
diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
index 4a3c1b86236e..cce3939704cf 100644
--- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
@@ -519,7 +519,7 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
OverlayableItem overlayable_item_bar(std::make_shared<Overlayable>(
"TaskBar", "overlay://theme"));
- overlayable_item_bar.policies |= OverlayableItem::Policy::kProductServices;
+ overlayable_item_bar.policies |= OverlayableItem::Policy::kPublic;
overlayable_item_bar.policies |= OverlayableItem::Policy::kVendor;
OverlayableItem overlayable_item_baz(std::make_shared<Overlayable>(
@@ -565,7 +565,7 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_THAT(overlayable_item.overlayable->name, Eq("TaskBar"));
EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme"));
- EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kProductServices
+ EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic
| OverlayableItem::Policy::kVendor));
search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/baz"));
diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp
index 921d634e583e..ad3674e16774 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -484,7 +484,7 @@ TEST_F(TableMergerTest, SetOverlayableLater) {
OverlayableItem overlayable_item(overlayable);
overlayable_item.policies |= OverlayableItem::Policy::kPublic;
- overlayable_item.policies |= OverlayableItem::Policy::kProductServices;
+ overlayable_item.policies |= OverlayableItem::Policy::kSystem;
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f)
@@ -506,7 +506,7 @@ TEST_F(TableMergerTest, SetOverlayableLater) {
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("CustomizableResources"));
EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://customization"));
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic
- | OverlayableItem::Policy::kProductServices));
+ | OverlayableItem::Policy::kSystem));
}
TEST_F(TableMergerTest, SameResourceDifferentNameFail) {