Merge "[view compiler] Cleanup: Delete duplicate LayoutValidationVisitor::VisitStartTag"
diff --git a/api/system-current.txt b/api/system-current.txt
index 593b45d..9200ce5 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -7424,6 +7424,7 @@
public abstract class ImsFeature {
ctor public ImsFeature();
method public abstract void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+ method public final int getSlotIndex();
method public abstract void onFeatureReady();
method public abstract void onFeatureRemoved();
method public final void setFeatureState(int);
@@ -7437,7 +7438,7 @@
field public static final int STATE_UNAVAILABLE = 0; // 0x0
}
- @Deprecated public static class ImsFeature.Capabilities {
+ public static class ImsFeature.Capabilities {
field @Deprecated protected int mCapabilities;
}
diff --git a/cmds/bootanimation/Android.bp b/cmds/bootanimation/Android.bp
index e17f735..3e5877b 100644
--- a/cmds/bootanimation/Android.bp
+++ b/cmds/bootanimation/Android.bp
@@ -40,24 +40,6 @@
"audioplay.cpp",
],
- product_variables: {
- product_is_iot: {
- shared_libs: [
- "libandroidthings",
- "libchrome",
- ],
- srcs: [
- "iot/iotbootanimation_main.cpp",
- "iot/BootAction.cpp",
- "iot/BootParameters.cpp",
- ],
- exclude_srcs: [
- "bootanimation_main.cpp",
- "audioplay.cpp",
- ],
- },
- },
-
init_rc: ["bootanim.rc"],
}
@@ -77,10 +59,4 @@
"libGLESv1_CM",
"libgui",
],
-
- product_variables: {
- product_is_iot: {
- init_rc: ["iot/bootanim_iot.rc"],
- },
- },
}
diff --git a/cmds/bootanimation/iot/BootAction.cpp b/cmds/bootanimation/iot/BootAction.cpp
deleted file mode 100644
index fa79744..0000000
--- a/cmds/bootanimation/iot/BootAction.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BootAction.h"
-
-#define LOG_TAG "BootAction"
-
-#include <dlfcn.h>
-
-#include <pio/peripheral_manager_client.h>
-#include <utils/Log.h>
-
-namespace android {
-
-BootAction::~BootAction() {
- if (mLibHandle != nullptr) {
- dlclose(mLibHandle);
- }
-}
-
-bool BootAction::init(const std::string& libraryPath,
- const std::vector<ABootActionParameter>& parameters) {
- APeripheralManagerClient* client = nullptr;
- ALOGD("Connecting to peripheralmanager");
- // Wait for peripheral manager to come up.
- while (client == nullptr) {
- client = APeripheralManagerClient_new();
- if (client == nullptr) {
- ALOGV("peripheralmanager is not up, sleeping before we check again.");
- usleep(250000);
- }
- }
- ALOGD("Peripheralmanager is up.");
- APeripheralManagerClient_delete(client);
-
-
- ALOGI("Loading boot action %s", libraryPath.c_str());
- mLibHandle = dlopen(libraryPath.c_str(), RTLD_NOW);
- if (mLibHandle == nullptr) {
- ALOGE("Unable to load library at %s :: %s",
- libraryPath.c_str(), dlerror());
- return false;
- }
-
- void* loaded = nullptr;
- if (!loadSymbol("boot_action_init", &loaded) || loaded == nullptr) {
- return false;
- }
- mLibInit = reinterpret_cast<libInit>(loaded);
-
- loaded = nullptr;
- if (!loadSymbol("boot_action_shutdown", &loaded) || loaded == nullptr) {
- return false;
- }
- mLibShutdown = reinterpret_cast<libShutdown>(loaded);
-
- // StartPart is considered optional, if it isn't exported by the library
- // we will still call init and shutdown.
- loaded = nullptr;
- if (!loadSymbol("boot_action_start_part", &loaded) || loaded == nullptr) {
- ALOGI("No boot_action_start_part found, action will not be told when "
- "Animation parts change.");
- } else {
- mLibStartPart = reinterpret_cast<libStartPart>(loaded);
- }
-
- ALOGD("Entering boot_action_init");
- bool result = mLibInit(parameters.data(), parameters.size());
- ALOGD("Returned from boot_action_init");
- return result;
-}
-
-void BootAction::startPart(int partNumber, int playNumber) {
- if (mLibStartPart == nullptr) return;
-
- ALOGD("Entering boot_action_start_part");
- mLibStartPart(partNumber, playNumber);
- ALOGD("Returned from boot_action_start_part");
-}
-
-void BootAction::shutdown() {
- ALOGD("Entering boot_action_shutdown");
- mLibShutdown();
- ALOGD("Returned from boot_action_shutdown");
-}
-
-bool BootAction::loadSymbol(const char* symbol, void** loaded) {
- *loaded = dlsym(mLibHandle, symbol);
- if (loaded == nullptr) {
- ALOGE("Unable to load symbol : %s :: %s", symbol, dlerror());
- return false;
- }
- return true;
-}
-
-} // namespace android
diff --git a/cmds/bootanimation/iot/BootAction.h b/cmds/bootanimation/iot/BootAction.h
deleted file mode 100644
index 5e2495f..0000000
--- a/cmds/bootanimation/iot/BootAction.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _BOOTANIMATION_BOOTACTION_H
-#define _BOOTANIMATION_BOOTACTION_H
-
-#include <string>
-#include <vector>
-
-#include <boot_action/boot_action.h> // libandroidthings native API.
-#include <utils/RefBase.h>
-
-namespace android {
-
-class BootAction : public RefBase {
-public:
- ~BootAction();
-
- // libraryPath is a fully qualified path to the target .so library.
- bool init(const std::string& libraryPath,
- const std::vector<ABootActionParameter>& parameters);
-
- // The animation is going to start playing partNumber for the playCount'th
- // time, update the action as needed.
- // This is run in the same thread as the boot animation,
- // you must not block here.
- void startPart(int partNumber, int playCount);
-
- // Shutdown the boot action, this will be called shortly before the
- // process is shut down to allow time for cleanup.
- void shutdown();
-
-private:
- typedef bool (*libInit)(const ABootActionParameter* parameters,
- size_t num_parameters);
- typedef void (*libStartPart)(int partNumber, int playNumber);
- typedef void (*libShutdown)();
-
- bool loadSymbol(const char* symbol, void** loaded);
-
- void* mLibHandle = nullptr;
- libInit mLibInit = nullptr;
- libStartPart mLibStartPart = nullptr;
- libShutdown mLibShutdown = nullptr;
-};
-
-} // namespace android
-
-
-#endif // _BOOTANIMATION_BOOTACTION_H
diff --git a/cmds/bootanimation/iot/BootParameters.cpp b/cmds/bootanimation/iot/BootParameters.cpp
deleted file mode 100644
index da6ad0d..0000000
--- a/cmds/bootanimation/iot/BootParameters.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "BootParameters.h"
-
-#define LOG_TAG "BootParameters"
-
-#include <fcntl.h>
-
-#include <string>
-
-#include <android-base/file.h>
-#include <base/json/json_parser.h>
-#include <base/json/json_reader.h>
-#include <base/json/json_value_converter.h>
-#include <utils/Log.h>
-
-using android::base::RemoveFileIfExists;
-using android::base::ReadFileToString;
-using base::JSONReader;
-using base::JSONValueConverter;
-using base::Value;
-
-namespace android {
-
-namespace {
-
-// Brightness and volume are stored as integer strings in next_boot.json.
-// They are divided by this constant to produce the actual float values in
-// range [0.0, 1.0]. This constant must match its counterpart in
-// DeviceManager.
-constexpr const float kFloatScaleFactor = 1000.0f;
-
-constexpr const char* kNextBootFile = "/data/misc/bootanimation/next_boot.json";
-constexpr const char* kLastBootFile = "/data/misc/bootanimation/last_boot.json";
-
-void swapBootConfigs() {
- // rename() will fail if next_boot.json doesn't exist, so delete
- // last_boot.json manually first.
- std::string err;
- if (!RemoveFileIfExists(kLastBootFile, &err))
- ALOGE("Unable to delete last boot file: %s", err.c_str());
-
- if (rename(kNextBootFile, kLastBootFile) && errno != ENOENT)
- ALOGE("Unable to swap boot files: %s", strerror(errno));
-
- int fd = open(kNextBootFile, O_CREAT, DEFFILEMODE);
- if (fd == -1) {
- ALOGE("Unable to create next boot file: %s", strerror(errno));
- } else {
- // Make next_boot.json writable to everyone so DeviceManagementService
- // can save saved_parameters there.
- if (fchmod(fd, DEFFILEMODE))
- ALOGE("Unable to set next boot file permissions: %s", strerror(errno));
- close(fd);
- }
-}
-
-} // namespace
-
-BootParameters::SavedBootParameters::SavedBootParameters()
- : brightness(-kFloatScaleFactor), volume(-kFloatScaleFactor) {}
-
-void BootParameters::SavedBootParameters::RegisterJSONConverter(
- JSONValueConverter<SavedBootParameters>* converter) {
- converter->RegisterIntField("brightness", &SavedBootParameters::brightness);
- converter->RegisterIntField("volume", &SavedBootParameters::volume);
- converter->RegisterRepeatedString("param_names",
- &SavedBootParameters::param_names);
- converter->RegisterRepeatedString("param_values",
- &SavedBootParameters::param_values);
-}
-
-BootParameters::BootParameters() {
- swapBootConfigs();
- loadParameters();
-}
-
-void BootParameters::loadParameters() {
- std::string contents;
- if (!ReadFileToString(kLastBootFile, &contents)) {
- if (errno != ENOENT)
- ALOGE("Unable to read from %s: %s", kLastBootFile, strerror(errno));
-
- return;
- }
-
- std::unique_ptr<Value> json = JSONReader::Read(contents);
- if (json.get() == nullptr) {
- return;
- }
-
- JSONValueConverter<SavedBootParameters> converter;
- if (converter.Convert(*(json.get()), &mRawParameters)) {
- mBrightness = mRawParameters.brightness / kFloatScaleFactor;
- mVolume = mRawParameters.volume / kFloatScaleFactor;
-
- if (mRawParameters.param_names.size() == mRawParameters.param_values.size()) {
- for (size_t i = 0; i < mRawParameters.param_names.size(); i++) {
- mParameters.push_back({
- .key = mRawParameters.param_names[i]->c_str(),
- .value = mRawParameters.param_values[i]->c_str()
- });
- }
- } else {
- ALOGW("Parameter names and values size mismatch");
- }
- }
-}
-
-} // namespace android
diff --git a/cmds/bootanimation/iot/BootParameters.h b/cmds/bootanimation/iot/BootParameters.h
deleted file mode 100644
index c10bd44..0000000
--- a/cmds/bootanimation/iot/BootParameters.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _BOOTANIMATION_BOOT_PARAMETERS_H_
-#define _BOOTANIMATION_BOOT_PARAMETERS_H_
-
-#include <list>
-#include <vector>
-
-#include <base/json/json_value_converter.h>
-#include <boot_action/boot_action.h> // libandroidthings native API.
-
-namespace android {
-
-// Provides access to the parameters set by DeviceManager.reboot().
-class BootParameters {
-public:
- // Constructor loads the parameters for this boot and swaps the param files
- // to clear the parameters for next boot.
- BootParameters();
-
- // Returns true if volume/brightness were explicitly set on reboot.
- bool hasVolume() const { return mVolume >= 0; }
- bool hasBrightness() const { return mBrightness >= 0; }
-
- // Returns volume/brightness in [0,1], or -1 if unset.
- float getVolume() const { return mVolume; }
- float getBrightness() const { return mBrightness; }
-
- // Returns the additional boot parameters that were set on reboot.
- const std::vector<ABootActionParameter>& getParameters() const { return mParameters; }
-
-private:
- // Raw boot saved_parameters loaded from .json.
- struct SavedBootParameters {
- int brightness;
- int volume;
- std::vector<std::unique_ptr<std::string>> param_names;
- std::vector<std::unique_ptr<std::string>> param_values;
-
- SavedBootParameters();
- static void RegisterJSONConverter(
- ::base::JSONValueConverter<SavedBootParameters>* converter);
- };
-
- void loadParameters();
-
- float mVolume = -1.f;
- float mBrightness = -1.f;
- std::vector<ABootActionParameter> mParameters;
-
- // ABootActionParameter is just a raw pointer so we need to keep the
- // original strings around to avoid losing them.
- SavedBootParameters mRawParameters;
-};
-
-} // namespace android
-
-
-#endif // _BOOTANIMATION_BOOT_PARAMETERS_H_
diff --git a/cmds/bootanimation/iot/bootanim_iot.rc b/cmds/bootanimation/iot/bootanim_iot.rc
deleted file mode 100644
index 2fc1336..0000000
--- a/cmds/bootanimation/iot/bootanim_iot.rc
+++ /dev/null
@@ -1,2 +0,0 @@
-on post-fs-data
- mkdir /data/misc/bootanimation 0777 root root
diff --git a/cmds/bootanimation/iot/iotbootanimation_main.cpp b/cmds/bootanimation/iot/iotbootanimation_main.cpp
deleted file mode 100644
index 00cef43..0000000
--- a/cmds/bootanimation/iot/iotbootanimation_main.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "IotBootAnimation"
-
-#include <base/files/file_util.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
-#include <cutils/properties.h>
-#include <sys/resource.h>
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <BootAnimation.h>
-
-#include "BootAction.h"
-#include "BootAnimationUtil.h"
-#include "BootParameters.h"
-
-using namespace android;
-
-// Create a typedef for readability.
-typedef android::BootAnimation::Animation Animation;
-
-namespace {
-
-constexpr const char* kDefaultLibName = "libbootaction.so";
-
-class BootActionAnimationCallbacks : public android::BootAnimation::Callbacks {
-public:
- BootActionAnimationCallbacks(std::unique_ptr<BootParameters> bootParameters)
- : mBootParameters(std::move(bootParameters)) {}
-
- void init(const Vector<Animation::Part>&) override {
- std::string library_path("/oem/lib/");
-
- // This value is optionally provided by the user and will be written to
- // /oem/oem.prop.
- char property[PROP_VALUE_MAX] = {0};
- property_get("ro.oem.bootactions.lib", property, kDefaultLibName);
- library_path += property;
-
- if (!::base::PathExists(::base::FilePath(library_path))) {
- ALOGI("Skipping boot actions: %s does not exist", library_path.c_str());
- return;
- }
-
- mBootAction = new BootAction();
- if (!mBootAction->init(library_path, mBootParameters->getParameters())) {
- mBootAction = NULL;
- }
- };
-
- void playPart(int partNumber, const Animation::Part&, int playNumber) override {
- if (mBootAction != nullptr) {
- mBootAction->startPart(partNumber, playNumber);
- }
- };
-
- void shutdown() override {
- if (mBootAction != nullptr) {
- // If we have a bootaction we want to wait until we are actually
- // told to shut down. If the animation exits early keep the action
- // running.
- char value[PROPERTY_VALUE_MAX] = {0};
- for (int exitRequested = 0; exitRequested == 0; ) {
- property_get("service.bootanim.exit", value, "0");
- exitRequested = atoi(value);
-
- // Poll value at 10hz.
- if (exitRequested == 0) {
- usleep(100000);
- }
- }
-
- mBootAction->shutdown();
- // Give it two seconds to shut down.
- sleep(2);
- mBootAction = nullptr;
- }
- };
-
-private:
- std::unique_ptr<BootParameters> mBootParameters;
- sp<BootAction> mBootAction = nullptr;
-};
-
-} // namespace
-
-int main() {
- setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
-
- // Clear our params for next boot no matter what.
- std::unique_ptr<BootParameters> bootParameters(new BootParameters());
-
- if (bootAnimationDisabled()) {
- ALOGI("boot animation disabled");
- return 0;
- }
-
- waitForSurfaceFlinger();
-
- sp<ProcessState> proc(ProcessState::self());
- ProcessState::self()->startThreadPool();
-
- sp<BootAnimation> boot = new BootAnimation(
- new BootActionAnimationCallbacks(std::move(bootParameters)));
-
- IPCThreadState::self()->joinThreadPool();
- return 0;
-}
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 984f22f..c712431 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -281,20 +281,7 @@
mAbortIdleOptimization.set(false);
long lowStorageThreshold = getLowStorageThreshold(context);
- // Optimize primary apks.
- int result = optimizePackages(pm, pkgs, lowStorageThreshold,
- /*isForPrimaryDex=*/ true);
- if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
- return result;
- }
- if (supportSecondaryDex()) {
- result = reconcileSecondaryDexFiles(pm.getDexManager());
- if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
- return result;
- }
- result = optimizePackages(pm, pkgs, lowStorageThreshold,
- /*isForPrimaryDex=*/ false);
- }
+ int result = idleOptimizePackages(pm, pkgs, lowStorageThreshold);
return result;
}
@@ -342,11 +329,20 @@
return 0;
}
- private int optimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
- long lowStorageThreshold, boolean isForPrimaryDex) {
+ private int idleOptimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
+ long lowStorageThreshold) {
ArraySet<String> updatedPackages = new ArraySet<>();
try {
+ final boolean supportSecondaryDex = supportSecondaryDex();
+
+ if (supportSecondaryDex) {
+ int result = reconcileSecondaryDexFiles(pm.getDexManager());
+ if (result == OPTIMIZE_ABORT_BY_JOB_SCHEDULER) {
+ return result;
+ }
+ }
+
// Only downgrade apps when space is low on device.
// Threshold is selected above the lowStorageThreshold so that we can pro-actively clean
// up disk before user hits the actual lowStorageThreshold.
@@ -359,43 +355,61 @@
pm.getUnusedPackages(mDowngradeUnusedAppsThresholdInMillis);
Log.d(TAG, "Unsused Packages " + String.join(",", unusedPackages));
- for (String pkg : unusedPackages) {
- int abortCode = abortIdleOptimizations(/*lowStorageThreshold*/ -1);
- if (abortCode != OPTIMIZE_CONTINUE) {
- // Should be aborted by the scheduler.
- return abortCode;
- }
- if (downgradePackage(pm, pkg, isForPrimaryDex)) {
- updatedPackages.add(pkg);
- }
- }
-
if (!unusedPackages.isEmpty()) {
+ for (String pkg : unusedPackages) {
+ int abortCode = abortIdleOptimizations(/*lowStorageThreshold*/ -1);
+ if (abortCode != OPTIMIZE_CONTINUE) {
+ // Should be aborted by the scheduler.
+ return abortCode;
+ }
+ if (downgradePackage(pm, pkg, /*isForPrimaryDex*/ true)) {
+ updatedPackages.add(pkg);
+ }
+ if (supportSecondaryDex) {
+ downgradePackage(pm, pkg, /*isForPrimaryDex*/ false);
+ }
+ }
+
pkgs = new ArraySet<>(pkgs);
pkgs.removeAll(unusedPackages);
}
}
- for (String pkg : pkgs) {
- int abortCode = abortIdleOptimizations(lowStorageThreshold);
- if (abortCode != OPTIMIZE_CONTINUE) {
- // Either aborted by the scheduler or no space left.
- return abortCode;
- }
-
- boolean dexOptPerformed = optimizePackage(pm, pkg, isForPrimaryDex);
- if (dexOptPerformed) {
- updatedPackages.add(pkg);
- }
+ int primaryResult = optimizePackages(pm, pkgs, lowStorageThreshold,
+ /*isForPrimaryDex*/ true, updatedPackages);
+ if (primaryResult != OPTIMIZE_PROCESSED) {
+ return primaryResult;
}
- return OPTIMIZE_PROCESSED;
+ if (!supportSecondaryDex) {
+ return OPTIMIZE_PROCESSED;
+ }
+
+ int secondaryResult = optimizePackages(pm, pkgs, lowStorageThreshold,
+ /*isForPrimaryDex*/ false, updatedPackages);
+ return secondaryResult;
} finally {
// Always let the pinner service know about changes.
notifyPinService(updatedPackages);
}
}
+ private int optimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
+ long lowStorageThreshold, boolean isForPrimaryDex, ArraySet<String> updatedPackages) {
+ for (String pkg : pkgs) {
+ int abortCode = abortIdleOptimizations(lowStorageThreshold);
+ if (abortCode != OPTIMIZE_CONTINUE) {
+ // Either aborted by the scheduler or no space left.
+ return abortCode;
+ }
+
+ boolean dexOptPerformed = optimizePackage(pm, pkg, isForPrimaryDex);
+ if (dexOptPerformed) {
+ updatedPackages.add(pkg);
+ }
+ }
+ return OPTIMIZE_PROCESSED;
+ }
/**
* Try to downgrade the package to a smaller compilation filter.
diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc
index 09f9c04..499c42e 100644
--- a/startop/view_compiler/dex_builder.cc
+++ b/startop/view_compiler/dex_builder.cc
@@ -108,6 +108,12 @@
case Instruction::Op::kSetStaticField:
out << "kSetStaticField";
return out;
+ case Instruction::Op::kGetInstanceField:
+ out << "kGetInstanceField";
+ return out;
+ case Instruction::Op::kSetInstanceField:
+ out << "kSetInstanceField";
+ return out;
}
}
@@ -246,6 +252,7 @@
field->parent = GetOrAddType(parent);
field->name = GetOrAddString(name);
field->type = GetOrAddType(type);
+ field->orig_index = dex_file_->fields_indexes.AllocateIndex();
dex_file_->fields_map[field->orig_index] = field;
field_decls_by_key_[key] = field;
return field;
@@ -384,7 +391,9 @@
return EncodeCast(instruction);
case Instruction::Op::kGetStaticField:
case Instruction::Op::kSetStaticField:
- return EncodeStaticFieldOp(instruction);
+ case Instruction::Op::kGetInstanceField:
+ case Instruction::Op::kSetInstanceField:
+ return EncodeFieldOp(instruction);
}
}
@@ -539,7 +548,8 @@
Encode21c(::art::Instruction::CHECK_CAST, RegisterValue(*instruction.dest()), type.value());
}
-void MethodBuilder::EncodeStaticFieldOp(const Instruction& instruction) {
+void MethodBuilder::EncodeFieldOp(const Instruction& instruction) {
+ const auto& args = instruction.args();
switch (instruction.opcode()) {
case Instruction::Op::kGetStaticField: {
CHECK(instruction.dest().has_value());
@@ -553,18 +563,36 @@
}
case Instruction::Op::kSetStaticField: {
CHECK(!instruction.dest().has_value());
- const auto& args = instruction.args();
CHECK_EQ(1, args.size());
CHECK(args[0].is_variable());
- Encode21c(::art::Instruction::SPUT,
+ Encode21c(::art::Instruction::SPUT, RegisterValue(args[0]), instruction.index_argument());
+ break;
+ }
+ case Instruction::Op::kGetInstanceField: {
+ CHECK(instruction.dest().has_value());
+ CHECK(instruction.dest()->is_variable());
+ CHECK_EQ(1, instruction.args().size());
+
+ Encode22c(::art::Instruction::IGET,
+ RegisterValue(*instruction.dest()),
RegisterValue(args[0]),
instruction.index_argument());
break;
}
- default: {
- LOG(FATAL) << "Unsupported static field operation";
+ case Instruction::Op::kSetInstanceField: {
+ CHECK(!instruction.dest().has_value());
+ CHECK_EQ(2, args.size());
+ CHECK(args[0].is_variable());
+ CHECK(args[1].is_variable());
+
+ Encode22c(::art::Instruction::IPUT,
+ RegisterValue(args[1]),
+ RegisterValue(args[0]),
+ instruction.index_argument());
+ break;
}
+ default: { LOG(FATAL) << "Unsupported field operation"; }
}
}
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
index 3f9ac43..292d659 100644
--- a/startop/view_compiler/dex_builder.h
+++ b/startop/view_compiler/dex_builder.h
@@ -153,6 +153,7 @@
kBranchEqz,
kBranchNEqz,
kCheckCast,
+ kGetInstanceField,
kGetStaticField,
kInvokeDirect,
kInvokeInterface,
@@ -163,6 +164,7 @@
kNew,
kReturn,
kReturnObject,
+ kSetInstanceField,
kSetStaticField
};
@@ -195,8 +197,9 @@
}
// Returns an object
template <typename... T>
- static inline Instruction InvokeVirtualObject(size_t index_argument, std::optional<const Value> dest,
- Value this_arg, T... args) {
+ static inline Instruction InvokeVirtualObject(size_t index_argument,
+ std::optional<const Value> dest, Value this_arg,
+ T... args) {
return Instruction{
Op::kInvokeVirtual, index_argument, /*result_is_object=*/true, dest, this_arg, args...};
}
@@ -209,8 +212,9 @@
}
// Returns an object
template <typename... T>
- static inline Instruction InvokeDirectObject(size_t index_argument, std::optional<const Value> dest,
- Value this_arg, T... args) {
+ static inline Instruction InvokeDirectObject(size_t index_argument,
+ std::optional<const Value> dest, Value this_arg,
+ T... args) {
return Instruction{
Op::kInvokeDirect, index_argument, /*result_is_object=*/true, dest, this_arg, args...};
}
@@ -218,20 +222,21 @@
template <typename... T>
static inline Instruction InvokeStatic(size_t index_argument, std::optional<const Value> dest,
T... args) {
- return Instruction{Op::kInvokeStatic, index_argument, /*result_is_object=*/false, dest, args...};
+ return Instruction{
+ Op::kInvokeStatic, index_argument, /*result_is_object=*/false, dest, args...};
}
// Returns an object
template <typename... T>
- static inline Instruction InvokeStaticObject(size_t index_argument, std::optional<const Value> dest,
- T... args) {
+ static inline Instruction InvokeStaticObject(size_t index_argument,
+ std::optional<const Value> dest, T... args) {
return Instruction{Op::kInvokeStatic, index_argument, /*result_is_object=*/true, dest, args...};
}
// For static calls.
template <typename... T>
static inline Instruction InvokeInterface(size_t index_argument, std::optional<const Value> dest,
T... args) {
- return Instruction{Op::kInvokeInterface, index_argument, /*result_is_object=*/false, dest, args...};
-
+ return Instruction{
+ Op::kInvokeInterface, index_argument, /*result_is_object=*/false, dest, args...};
}
static inline Instruction GetStaticField(size_t field_id, Value dest) {
@@ -239,9 +244,18 @@
}
static inline Instruction SetStaticField(size_t field_id, Value value) {
- return Instruction{Op::kSetStaticField, field_id, /*result_is_object=*/false, /*dest=*/{}, value};
+ return Instruction{
+ Op::kSetStaticField, field_id, /*result_is_object=*/false, /*dest=*/{}, value};
}
+ static inline Instruction GetField(size_t field_id, Value dest, Value object) {
+ return Instruction{Op::kGetInstanceField, field_id, /*result_is_object=*/false, dest, object};
+ }
+
+ static inline Instruction SetField(size_t field_id, Value object, Value value) {
+ return Instruction{
+ Op::kSetInstanceField, field_id, /*result_is_object=*/false, /*dest=*/{}, object, value};
+ }
///////////////
// Accessors //
@@ -255,10 +269,14 @@
private:
inline Instruction(Op opcode, size_t index_argument, std::optional<const Value> dest)
- : opcode_{opcode}, index_argument_{index_argument}, result_is_object_{false}, dest_{dest}, args_{} {}
+ : opcode_{opcode},
+ index_argument_{index_argument},
+ result_is_object_{false},
+ dest_{dest},
+ args_{} {}
template <typename... T>
- inline constexpr Instruction(Op opcode, size_t index_argument, bool result_is_object,
+ inline Instruction(Op opcode, size_t index_argument, bool result_is_object,
std::optional<const Value> dest, T... args)
: opcode_{opcode},
index_argument_{index_argument},
@@ -331,7 +349,7 @@
void EncodeBranch(art::Instruction::Code op, const Instruction& instruction);
void EncodeNew(const Instruction& instruction);
void EncodeCast(const Instruction& instruction);
- void EncodeStaticFieldOp(const Instruction& instruction);
+ void EncodeFieldOp(const Instruction& instruction);
// Low-level instruction format encoding. See
// https://source.android.com/devices/tech/dalvik/instruction-formats for documentation of
@@ -364,6 +382,14 @@
buffer_.push_back(b);
}
+ inline void Encode22c(art::Instruction::Code opcode, uint8_t a, uint8_t b, uint16_t c) {
+ // b|a|op|bbbb
+ CHECK(IsShortRegister(a));
+ CHECK(IsShortRegister(b));
+ buffer_.push_back((b << 12) | (a << 8) | opcode);
+ buffer_.push_back(c);
+ }
+
inline void Encode32x(art::Instruction::Code opcode, uint16_t a, uint16_t b) {
buffer_.push_back(opcode);
buffer_.push_back(a);
diff --git a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
index 3138e71..93496d0 100644
--- a/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
+++ b/startop/view_compiler/dex_builder_test/src/android/startop/test/DexBuilderTest.java
@@ -190,4 +190,25 @@
method.invoke(null);
Assert.assertEquals(7, TestClass.staticInteger);
}
+
+ @Test
+ public void readInstanceField() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("readInstanceField", TestClass.class);
+ TestClass obj = new TestClass();
+ obj.instanceField = 5;
+ Assert.assertEquals(5, method.invoke(null, obj));
+ }
+
+ @Test
+ public void setInstanceField() throws Exception {
+ ClassLoader loader = loadDexFile("simple.dex");
+ Class clazz = loader.loadClass("android.startop.test.testcases.SimpleTests");
+ Method method = clazz.getMethod("setInstanceField", TestClass.class);
+ TestClass obj = new TestClass();
+ obj.instanceField = 5;
+ method.invoke(null, obj);
+ Assert.assertEquals(7, obj.instanceField);
+ }
}
diff --git a/startop/view_compiler/dex_testcase_generator.cc b/startop/view_compiler/dex_testcase_generator.cc
index fee5e72..6dedf24 100644
--- a/startop/view_compiler/dex_testcase_generator.cc
+++ b/startop/view_compiler/dex_testcase_generator.cc
@@ -282,15 +282,15 @@
method.Encode();
}(castObjectToString);
+ TypeDescriptor test_class = TypeDescriptor::FromClassname("android.startop.test.TestClass");
+
// Read a static field
- // integer readStaticField() { return TestClass.staticInteger; }
+ // int readStaticField() { return TestClass.staticInteger; }
MethodBuilder readStaticField{
cbuilder.CreateMethod("readStaticField", Prototype{TypeDescriptor::Int()})};
[&](MethodBuilder& method) {
const ir::FieldDecl* field =
- dex_file.GetOrAddField(TypeDescriptor::FromClassname("android.startop.test.TestClass"),
- "staticInteger",
- TypeDescriptor::Int());
+ dex_file.GetOrAddField(test_class, "staticInteger", TypeDescriptor::Int());
Value result{method.MakeRegister()};
method.AddInstruction(Instruction::GetStaticField(field->orig_index, result));
method.BuildReturn(result, /*is_object=*/false);
@@ -303,9 +303,7 @@
cbuilder.CreateMethod("setStaticField", Prototype{TypeDescriptor::Void()})};
[&](MethodBuilder& method) {
const ir::FieldDecl* field =
- dex_file.GetOrAddField(TypeDescriptor::FromClassname("android.startop.test.TestClass"),
- "staticInteger",
- TypeDescriptor::Int());
+ dex_file.GetOrAddField(test_class, "staticInteger", TypeDescriptor::Int());
Value number{method.MakeRegister()};
method.BuildConst4(number, 7);
method.AddInstruction(Instruction::SetStaticField(field->orig_index, number));
@@ -313,6 +311,33 @@
method.Encode();
}(setStaticField);
+ // Read an instance field
+ // int readInstanceField(TestClass obj) { return obj.instanceField; }
+ MethodBuilder readInstanceField{
+ cbuilder.CreateMethod("readInstanceField", Prototype{TypeDescriptor::Int(), test_class})};
+ [&](MethodBuilder& method) {
+ const ir::FieldDecl* field =
+ dex_file.GetOrAddField(test_class, "instanceField", TypeDescriptor::Int());
+ Value result{method.MakeRegister()};
+ method.AddInstruction(Instruction::GetField(field->orig_index, result, Value::Parameter(0)));
+ method.BuildReturn(result, /*is_object=*/false);
+ method.Encode();
+ }(readInstanceField);
+
+ // Set an instance field
+ // void setInstanceField(TestClass obj) { obj.instanceField = 7; }
+ MethodBuilder setInstanceField{
+ cbuilder.CreateMethod("setInstanceField", Prototype{TypeDescriptor::Void(), test_class})};
+ [&](MethodBuilder& method) {
+ const ir::FieldDecl* field =
+ dex_file.GetOrAddField(test_class, "instanceField", TypeDescriptor::Int());
+ Value number{method.MakeRegister()};
+ method.BuildConst4(number, 7);
+ method.AddInstruction(Instruction::SetField(field->orig_index, Value::Parameter(0), number));
+ method.BuildReturn();
+ method.Encode();
+ }(setInstanceField);
+
slicer::MemView image{dex_file.CreateImage()};
std::ofstream out_file(outdir + "/simple.dex");
out_file.write(image.ptr<const char>(), image.size());
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 74af6bf..3bec8b0 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -132,15 +132,20 @@
public @interface ImsState {}
/**
- * This {@link ImsFeature}'s state is unavailable and should not be communicated with.
+ * This {@link ImsFeature}'s state is unavailable and should not be communicated with. This will
+ * remove all bindings back to the framework. Any attempt to communicate with the framework
+ * during this time will result in an {@link IllegalStateException}.
*/
public static final int STATE_UNAVAILABLE = 0;
/**
- * This {@link ImsFeature} state is initializing and should not be communicated with.
+ * This {@link ImsFeature} state is initializing and should not be communicated with. This will
+ * remove all bindings back to the framework. Any attempt to communicate with the framework
+ * during this time will result in an {@link IllegalStateException}.
*/
public static final int STATE_INITIALIZING = 1;
/**
- * This {@link ImsFeature} is ready for communication.
+ * This {@link ImsFeature} is ready for communication. Do not attempt to call framework methods
+ * until {@link #onFeatureReady()} is called.
*/
public static final int STATE_READY = 2;
@@ -208,11 +213,14 @@
/**
* Contains the capabilities defined and supported by an ImsFeature in the form of a bit mask.
+ * <p>
+ * Typically this class is not used directly, but rather extended in subclasses of
+ * {@link ImsFeature} to provide service specific capabilities.
* @hide
- * @deprecated Use {@link MmTelFeature.MmTelCapabilities} instead.
*/
- @SystemApi // SystemApi only because it was leaked through type usage in a previous release.
+ @SystemApi
public static class Capabilities {
+ /** @deprecated Use getters and accessors instead. */
protected int mCapabilities = 0;
/**
@@ -305,12 +313,12 @@
/** @hide */
protected final Object mLock = new Object();
- private final Set<IImsFeatureStatusCallback> mStatusCallbacks = Collections.newSetFromMap(
- new WeakHashMap<IImsFeatureStatusCallback, Boolean>());
+ private final Set<IImsFeatureStatusCallback> mStatusCallbacks =
+ Collections.newSetFromMap(new WeakHashMap<>());
private @ImsState int mState = STATE_UNAVAILABLE;
private int mSlotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
- private final RemoteCallbackList<IImsCapabilityCallback> mCapabilityCallbacks
- = new RemoteCallbackList<>();
+ private final RemoteCallbackList<IImsCapabilityCallback> mCapabilityCallbacks =
+ new RemoteCallbackList<>();
private Capabilities mCapabilityStatus = new Capabilities();
/**
@@ -322,6 +330,16 @@
}
/**
+ * @return The SIM slot index associated with this ImsFeature.
+ *
+ * @see SubscriptionManager#getSubscriptionIds(int) for more information on getting the
+ * subscription IDs associated with this slot.
+ */
+ public final int getSlotIndex() {
+ return mSlotId;
+ }
+
+ /**
* @return The current state of the feature, defined as {@link #STATE_UNAVAILABLE},
* {@link #STATE_INITIALIZING}, or {@link #STATE_READY}.
* @hide
@@ -490,7 +508,9 @@
public abstract void onFeatureRemoved();
/**
- * Called when the feature has been initialized and communication with the framework is set up.
+ * Called after this ImsFeature has been initialized and has been set to the
+ * {@link ImsState#STATE_READY} state.
+ * <p>
* Any attempt by this feature to access the framework before this method is called will return
* with an {@link IllegalStateException}.
* The IMS provider should use this method to trigger registration for this feature on the IMS