/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include namespace android { class BpBinder; class ProcessState; namespace internal { // Stability encodes how a binder changes over time. There are two levels of // stability: // 1). the interface stability - this is how a particular set of API calls (a // particular ordering of things like writeInt32/readInt32) are changed over // time. If one release, we have 'writeInt32' and the next release, we have // 'writeInt64', then this interface doesn't have a very stable // Stability::Level. Usually this ordering is controlled by a .aidl file. // 2). the wire format stability - this is how these API calls map to actual // bytes that are written to the wire (literally, this is how they are written // to the kernel inside of IBinder::transact, but it may be expanded to other // wires in the future). For instance, writeInt32 in binder translates to // writing a 4-byte little-endian integer in two's complement. You can imagine // in the future, we change writeInt32/readInt32 to instead write 8-bytes with // that integer and some check bits. In this case, the wire format changes, // but as long as a client libbinder knows to keep on writing a 4-byte value // to old servers, and new servers know how to interpret the 8-byte result, // they can still communicate. // // This class is specifically about (1). (2) is not currently tracked by // libbinder for regular binder calls, and everything on the system uses the // same copy of libbinder. class Stability final { public: // Given a binder interface at a certain stability, there may be some // requirements associated with that higher stability level. For instance, a // VINTF stability binder is required to be in the VINTF manifest. This API // can be called to use that same interface within the local partition. LIBBINDER_EXPORTED static void forceDowngradeToLocalStability(const sp& binder); // WARNING: Below APIs are only ever expected to be called by auto-generated code. // Instead of calling them, you should set the stability of a .aidl interface // WARNING: The only client of // - forceDowngradeToSystemStability() and; // - korceDowngradeToVendorStability() // should be AIBinder_forceDowngradeToLocalStability(). // // getLocalLevel() in libbinder returns Level::SYSTEM when called // from libbinder_ndk (even on vendor partition). So we explicitly provide // these methods for use by the NDK API: // AIBinder_forceDowngradeToLocalStability(). // // This allows correctly downgrading the binder's stability to either system/vendor, // depending on the partition. // Given a binder interface at a certain stability, there may be some // requirements associated with that higher stability level. For instance, a // VINTF stability binder is required to be in the VINTF manifest. This API // can be called to use that same interface within the vendor partition. LIBBINDER_EXPORTED static void forceDowngradeToVendorStability(const sp& binder); // Given a binder interface at a certain stability, there may be some // requirements associated with that higher stability level. For instance, a // VINTF stability binder is required to be in the VINTF manifest. This API // can be called to use that same interface within the system partition. LIBBINDER_EXPORTED static void forceDowngradeToSystemStability(const sp& binder); // WARNING: This is only ever expected to be called by auto-generated code. You likely want to // change or modify the stability class of the interface you are using. // This must be called as soon as the binder in question is constructed. No thread safety // is provided. // E.g. stability is according to libbinder compilation unit LIBBINDER_EXPORTED static void markCompilationUnit(IBinder* binder); // WARNING: This is only ever expected to be called by auto-generated code. You likely want to // change or modify the stability class of the interface you are using. // This must be called as soon as the binder in question is constructed. No thread safety // is provided. // E.g. stability is according to libbinder_ndk or Java SDK AND the interface // expressed here is guaranteed to be stable for multiple years (Stable AIDL) LIBBINDER_EXPORTED static void markVintf(IBinder* binder); // WARNING: for debugging only LIBBINDER_EXPORTED static std::string debugToString(const sp& binder); // WARNING: This is only ever expected to be called by auto-generated code or tests. // You likely want to change or modify the stability of the interface you are using. // This must be called as soon as the binder in question is constructed. No thread safety // is provided. // E.g. stability is according to libbinder_ndk or Java SDK AND the interface // expressed here is guaranteed to be stable for multiple years (Stable AIDL) // If this is called when __ANDROID_VNDK__ is not defined, then it is UB and will likely // break the device during GSI or other tests. LIBBINDER_EXPORTED static void markVndk(IBinder* binder); // Returns true if the binder needs to be declared in the VINTF manifest or // else false if the binder is local to the current partition. LIBBINDER_EXPORTED static bool requiresVintfDeclaration(const sp& binder); private: // Parcel needs to read/write stability level in an unstable format. friend ::android::Parcel; // only expose internal APIs inside of libbinder, for checking stability friend ::android::BpBinder; // so that it can mark the context object (only the root object doesn't go // through Parcel) friend ::android::ProcessState; static void tryMarkCompilationUnit(IBinder* binder); // Currently, we use int16_t for Level so that it can fit in BBinder. // However, on the wire, we have 4 bytes reserved for stability, so whenever // we ingest a Level, we always accept an int32_t. enum Level : int16_t { UNDECLARED = 0, VENDOR = 0b000011, SYSTEM = 0b001100, VINTF = 0b111111, }; // returns the stability according to how this was built static Level getLocalLevel(); // Downgrades binder stability to the specified level. static void forceDowngradeToStability(const sp& binder, Level level); enum { REPR_NONE = 0, REPR_LOG = 1, REPR_ALLOW_DOWNGRADE = 2, }; // applies stability to binder if stability level is known __attribute__((warn_unused_result)) static status_t setRepr(IBinder* binder, int32_t setting, uint32_t flags); // get stability information as encoded on the wire static int16_t getRepr(IBinder* binder); // whether a transaction on binder is allowed, if the transaction // is done from a context with a specific stability level static bool check(int16_t provided, Level required); static bool isDeclaredLevel(int32_t level); static std::string levelString(int32_t level); Stability(); }; } // namespace internal } // namespace android