/* * 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 namespace android { namespace internal { void Stability::markCompilationUnit(IBinder* binder) { status_t result = set(binder, kLocalStability, true /*log*/); LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object."); } void Stability::markVintf(IBinder* binder) { status_t result = set(binder, Level::VINTF, true /*log*/); LOG_ALWAYS_FATAL_IF(result != OK, "Should only mark known object."); } void Stability::tryMarkCompilationUnit(IBinder* binder) { (void) set(binder, kLocalStability, false /*log*/); } status_t Stability::set(IBinder* binder, int32_t stability, bool log) { Level currentStability = get(binder); // null binder is always written w/ 'UNDECLARED' stability if (binder == nullptr) { if (stability == UNDECLARED) { return OK; } else { if (log) { ALOGE("Null binder written with stability %s.", stabilityString(stability).c_str()); } return BAD_TYPE; } } if (!isDeclaredStability(stability)) { if (log) { ALOGE("Can only set known stability, not %d.", stability); } return BAD_TYPE; } if (currentStability != Level::UNDECLARED && currentStability != stability) { if (log) { ALOGE("Interface being set with %s but it is already marked as %s.", stabilityString(stability).c_str(), stabilityString(currentStability).c_str()); } return BAD_TYPE; } if (currentStability == stability) return OK; binder->attachObject( reinterpret_cast(&Stability::get), reinterpret_cast(stability), nullptr /*cleanupCookie*/, nullptr /*cleanup function*/); return OK; } Stability::Level Stability::get(IBinder* binder) { if (binder == nullptr) return UNDECLARED; return static_cast(reinterpret_cast( binder->findObject(reinterpret_cast(&Stability::get)))); } bool Stability::check(int32_t provided, Level required) { bool stable = (provided & required) == required; if (!isDeclaredStability(provided) && provided != UNDECLARED) { ALOGE("Unknown stability when checking interface stability %d.", provided); stable = false; } if (!stable) { ALOGE("Interface with %s cannot accept interface with %s.", stabilityString(required).c_str(), stabilityString(provided).c_str()); } return stable; } bool Stability::isDeclaredStability(int32_t stability) { return stability == VENDOR || stability == SYSTEM || stability == VINTF; } std::string Stability::stabilityString(int32_t stability) { switch (stability) { case Level::UNDECLARED: return "undeclared stability"; case Level::VENDOR: return "vendor stability"; case Level::SYSTEM: return "system stability"; case Level::VINTF: return "vintf stability"; } return "unknown stability " + std::to_string(stability); } } // namespace internal } // namespace stability