Merge "Update comments for smart selection actions."
diff --git a/api/current.txt b/api/current.txt
index 568f4c4..f750e33 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -41867,6 +41867,9 @@
field public static final java.lang.String KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL = "always_show_emergency_alert_onoff_bool";
field public static final java.lang.String KEY_APN_EXPAND_BOOL = "apn_expand_bool";
field public static final java.lang.String KEY_AUTO_RETRY_ENABLED_BOOL = "auto_retry_enabled_bool";
+ field public static final java.lang.String KEY_CALL_BARRING_SUPPORTS_DEACTIVATE_ALL_BOOL = "call_barring_supports_deactivate_all_bool";
+ field public static final java.lang.String KEY_CALL_BARRING_SUPPORTS_PASSWORD_CHANGE_BOOL = "call_barring_supports_password_change_bool";
+ field public static final java.lang.String KEY_CALL_BARRING_VISIBILITY_BOOL = "call_barring_visibility_bool";
field public static final java.lang.String KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY = "call_forwarding_blocks_while_roaming_string_array";
field public static final java.lang.String KEY_CARRIER_ALLOW_TURNOFF_IMS_BOOL = "carrier_allow_turnoff_ims_bool";
field public static final java.lang.String KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS = "carrier_data_call_permanent_failure_strings";
@@ -44486,6 +44489,11 @@
method public abstract void chooseHeight(java.lang.CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt);
}
+ public static class LineHeightSpan.Standard implements android.text.style.LineHeightSpan {
+ ctor public LineHeightSpan.Standard(int);
+ method public void chooseHeight(java.lang.CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt);
+ }
+
public static abstract interface LineHeightSpan.WithDensity implements android.text.style.LineHeightSpan {
method public abstract void chooseHeight(java.lang.CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt, android.text.TextPaint);
}
diff --git a/core/java/android/text/style/LineHeightSpan.java b/core/java/android/text/style/LineHeightSpan.java
index 50ee5f3..2742ae0 100644
--- a/core/java/android/text/style/LineHeightSpan.java
+++ b/core/java/android/text/style/LineHeightSpan.java
@@ -16,11 +16,16 @@
package android.text.style;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Px;
import android.graphics.Paint;
import android.text.TextPaint;
+import com.android.internal.util.Preconditions;
+
/**
- * The classes that affect the height of the line should implement this interface.
+ * The classes that affect the line height of paragraph should implement this interface.
*/
public interface LineHeightSpan extends ParagraphStyle, WrapTogetherSpan {
/**
@@ -38,8 +43,8 @@
Paint.FontMetricsInt fm);
/**
- * The classes that affect the height of the line with respect to density, should implement this
- * interface.
+ * The classes that affect the line height of paragraph with respect to density,
+ * should implement this interface.
*/
public interface WithDensity extends LineHeightSpan {
@@ -57,4 +62,38 @@
int spanstartv, int lineHeight,
Paint.FontMetricsInt fm, TextPaint paint);
}
+
+ /**
+ * Default implementation of the {@link LineHeightSpan}, which changes the line height of the
+ * attached paragraph.
+ * <p>
+ * LineHeightSpan will change the line height of the entire paragraph, even though it
+ * covers only part of the paragraph.
+ * </p>
+ */
+ class Standard implements LineHeightSpan {
+
+ private final @Px int mHeight;
+ /**
+ * Set the line height of the paragraph to <code>height</code> physical pixels.
+ */
+ public Standard(@Px @IntRange(from = 1) int height) {
+ Preconditions.checkArgument(height > 0, "Height:" + height + "must be positive");
+ mHeight = height;
+ }
+
+ @Override
+ public void chooseHeight(@NonNull CharSequence text, int start, int end,
+ int spanstartv, int lineHeight,
+ @NonNull Paint.FontMetricsInt fm) {
+ final int originHeight = fm.descent - fm.ascent;
+ // If original height is not positive, do nothing.
+ if (originHeight <= 0) {
+ return;
+ }
+ final float ratio = mHeight * 1.0f / originHeight;
+ fm.descent = Math.round(fm.descent * ratio);
+ fm.ascent = fm.descent - mHeight;
+ }
+ }
}
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 3280d47..8e2786d 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -215,11 +215,11 @@
final Point windowCoords = getCurrentClampedWindowCoordinates();
final InternalPopupWindow currentWindowInstance = mWindow;
sPixelCopyHandlerThread.getThreadHandler().post(() -> {
- if (mWindow != currentWindowInstance) {
- // The magnifier was dismissed (and maybe shown again) in the meantime.
- return;
- }
synchronized (mLock) {
+ if (mWindow != currentWindowInstance) {
+ // The magnifier was dismissed (and maybe shown again) in the meantime.
+ return;
+ }
mWindow.setContentPositionForNextDraw(windowCoords.x, windowCoords.y);
}
});
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index d582983..edce305 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -72,6 +72,7 @@
"libft2",
"libminikin",
"libandroidfw",
+ "libcrypto",
],
static_libs: [
"libEGL_blobCache",
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index 6700748..073b481 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -18,6 +18,8 @@
#include <algorithm>
#include <log/log.h>
#include <thread>
+#include <array>
+#include <openssl/sha.h>
#include "FileBlobCache.h"
#include "Properties.h"
#include "utils/TraceUtils.h"
@@ -41,7 +43,40 @@
return sCache;
}
-void ShaderCache::initShaderDiskCache() {
+bool ShaderCache::validateCache(const void* identity, ssize_t size) {
+ if (nullptr == identity && size == 0)
+ return true;
+
+ if (nullptr == identity || size < 0) {
+ if (CC_UNLIKELY(Properties::debugLevel & kDebugCaches)) {
+ ALOGW("ShaderCache::validateCache invalid cache identity");
+ }
+ mBlobCache->clear();
+ return false;
+ }
+
+ SHA256_CTX ctx;
+ SHA256_Init(&ctx);
+
+ SHA256_Update(&ctx, identity, size);
+ mIDHash.resize(SHA256_DIGEST_LENGTH);
+ SHA256_Final(mIDHash.data(), &ctx);
+
+ std::array<uint8_t, SHA256_DIGEST_LENGTH> hash;
+ auto key = sIDKey;
+ auto loaded = mBlobCache->get(&key, sizeof(key), hash.data(), hash.size());
+
+ if (loaded && std::equal(hash.begin(), hash.end(), mIDHash.begin()))
+ return true;
+
+ if (CC_UNLIKELY(Properties::debugLevel & kDebugCaches)) {
+ ALOGW("ShaderCache::validateCache cache validation fails");
+ }
+ mBlobCache->clear();
+ return false;
+}
+
+void ShaderCache::initShaderDiskCache(const void* identity, ssize_t size) {
ATRACE_NAME("initShaderDiskCache");
std::lock_guard<std::mutex> lock(mMutex);
@@ -50,6 +85,7 @@
// desktop / laptop GPUs. Thus, disable the shader disk cache for emulator builds.
if (!Properties::runningInEmulator && mFilename.length() > 0) {
mBlobCache.reset(new FileBlobCache(maxKeySize, maxValueSize, maxTotalSize, mFilename));
+ validateCache(identity, size);
mInitialized = true;
}
}
@@ -104,6 +140,18 @@
return SkData::MakeFromMalloc(valueBuffer, valueSize);
}
+void ShaderCache::saveToDiskLocked() {
+ ATRACE_NAME("ShaderCache::saveToDiskLocked");
+ if (mInitialized && mBlobCache && mSavePending) {
+ if (mIDHash.size()) {
+ auto key = sIDKey;
+ mBlobCache->set(&key, sizeof(key), mIDHash.data(), mIDHash.size());
+ }
+ mBlobCache->writeToFile();
+ }
+ mSavePending = false;
+}
+
void ShaderCache::store(const SkData& key, const SkData& data) {
ATRACE_NAME("ShaderCache::store");
std::lock_guard<std::mutex> lock(mMutex);
@@ -129,11 +177,7 @@
std::thread deferredSaveThread([this]() {
sleep(mDeferredSaveDelay);
std::lock_guard<std::mutex> lock(mMutex);
- ATRACE_NAME("ShaderCache::saveToDisk");
- if (mInitialized && mBlobCache) {
- mBlobCache->writeToFile();
- }
- mSavePending = false;
+ saveToDiskLocked();
});
deferredSaveThread.detach();
}
diff --git a/libs/hwui/pipeline/skia/ShaderCache.h b/libs/hwui/pipeline/skia/ShaderCache.h
index 27473d6..82804cf 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.h
+++ b/libs/hwui/pipeline/skia/ShaderCache.h
@@ -40,12 +40,21 @@
ANDROID_API static ShaderCache& get();
/**
- * "initShaderDiskCache" loads the serialized cache contents from disk and puts the ShaderCache
- * into an initialized state, such that it is able to insert and retrieve entries from the
- * cache. This should be called when HWUI pipeline is initialized. When not in the initialized
- * state the load and store methods will return without performing any cache operations.
+ * initShaderDiskCache" loads the serialized cache contents from disk,
+ * optionally checks that the on-disk cache matches a provided identity,
+ * and puts the ShaderCache into an initialized state, such that it is
+ * able to insert and retrieve entries from the cache. If identity is
+ * non-null and validation fails, the cache is initialized but contains
+ * no data. If size is less than zero, the cache is initilaized but
+ * contains no data.
+ *
+ * This should be called when HWUI pipeline is initialized. When not in
+ * the initialized state the load and store methods will return without
+ * performing any cache operations.
*/
- virtual void initShaderDiskCache();
+ virtual void initShaderDiskCache(const void *identity, ssize_t size);
+
+ virtual void initShaderDiskCache() { initShaderDiskCache(nullptr, 0); }
/**
* "setFilename" sets the name of the file that should be used to store
@@ -83,6 +92,19 @@
BlobCache* getBlobCacheLocked();
/**
+ * "validateCache" updates the cache to match the given identity. If the
+ * cache currently has the wrong identity, all entries in the cache are cleared.
+ */
+ bool validateCache(const void* identity, ssize_t size);
+
+ /**
+ * "saveToDiskLocked" attemps to save the current contents of the cache to
+ * disk. If the identity hash exists, we will insert the identity hash into
+ * the cache for next validation.
+ */
+ void saveToDiskLocked();
+
+ /**
* "mInitialized" indicates whether the ShaderCache is in the initialized
* state. It is initialized to false at construction time, and gets set to
* true when initialize is called.
@@ -111,6 +133,15 @@
std::string mFilename;
/**
+ * "mIDHash" is the current identity hash for the cache validation. It is
+ * initialized to an empty vector at construction time, and its content is
+ * generated in the call of the validateCache method. An empty vector
+ * indicates that cache validation is not performed, and the hash should
+ * not be stored on disk.
+ */
+ std::vector<uint8_t> mIDHash;
+
+ /**
* "mSavePending" indicates whether or not a deferred save operation is
* pending. Each time a key/value pair is inserted into the cache via
* load, a deferred save is initiated if one is not already pending.
@@ -140,6 +171,11 @@
*/
static ShaderCache sCache;
+ /**
+ * "sIDKey" is the cache key of the identity hash
+ */
+ static constexpr uint8_t sIDKey = 0;
+
friend class ShaderCacheTestUtils; //used for unit testing
};
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index bec80b1e..82bfc49 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -50,7 +50,6 @@
mVectorDrawableAtlas = new skiapipeline::VectorDrawableAtlas(
mMaxSurfaceArea / 2,
skiapipeline::VectorDrawableAtlas::StorageMode::disallowSharedSurface);
- skiapipeline::ShaderCache::get().initShaderDiskCache();
}
void CacheManager::reset(sk_sp<GrContext> context) {
@@ -103,7 +102,7 @@
}
};
-void CacheManager::configureContext(GrContextOptions* contextOptions) {
+void CacheManager::configureContext(GrContextOptions* contextOptions, const void* identity, ssize_t size) {
contextOptions->fAllowPathMaskCaching = true;
float screenMP = mMaxSurfaceArea / 1024.0f / 1024.0f;
@@ -133,7 +132,9 @@
contextOptions->fExecutor = mTaskProcessor.get();
}
- contextOptions->fPersistentCache = &skiapipeline::ShaderCache::get();
+ auto& cache = skiapipeline::ShaderCache::get();
+ cache.initShaderDiskCache(identity, size);
+ contextOptions->fPersistentCache = &cache;
contextOptions->fGpuPathRenderers &= ~GpuPathRenderers::kCoverageCounting;
}
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index 7d73352..35fc91a 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -44,7 +44,7 @@
public:
enum class TrimMemoryMode { Complete, UiHidden };
- void configureContext(GrContextOptions* context);
+ void configureContext(GrContextOptions* context, const void* identity, ssize_t size);
void trimMemory(TrimMemoryMode mode);
void trimStaleResources();
void dumpMemoryUsage(String8& log, const RenderState* renderState = nullptr);
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index c1284ec..36ffaee 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -191,7 +191,9 @@
GrContextOptions options;
options.fPreferExternalImagesOverES3 = true;
options.fDisableDistanceFieldPaths = true;
- cacheManager().configureContext(&options);
+ auto glesVersion = reinterpret_cast<const char*>(glGetString(GL_VERSION));
+ auto size = glesVersion ? strlen(glesVersion) : -1;
+ cacheManager().configureContext(&options, glesVersion, size);
sk_sp<GrContext> grContext(GrContext::MakeGL(std::move(glInterface), options));
LOG_ALWAYS_FATAL_IF(!grContext.get());
setGrContext(grContext);
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 1517f57..cc4b87a 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -391,7 +391,8 @@
GrContextOptions options;
options.fDisableDistanceFieldPaths = true;
- mRenderThread.cacheManager().configureContext(&options);
+ // TODO: get a string describing the SPIR-V compiler version and use it here
+ mRenderThread.cacheManager().configureContext(&options, nullptr, 0);
sk_sp<GrContext> grContext(GrContext::MakeVulkan(backendContext, options));
LOG_ALWAYS_FATAL_IF(!grContext.get());
mRenderThread.setGrContext(grContext);
diff --git a/libs/hwui/tests/unit/ShaderCacheTests.cpp b/libs/hwui/tests/unit/ShaderCacheTests.cpp
index 43080a9..1433aa0 100644
--- a/libs/hwui/tests/unit/ShaderCacheTests.cpp
+++ b/libs/hwui/tests/unit/ShaderCacheTests.cpp
@@ -48,11 +48,18 @@
*/
static void terminate(ShaderCache& cache, bool saveContent) {
std::lock_guard<std::mutex> lock(cache.mMutex);
- if (cache.mInitialized && cache.mBlobCache && saveContent) {
- cache.mBlobCache->writeToFile();
- }
+ cache.mSavePending = saveContent;
+ cache.saveToDiskLocked();
cache.mBlobCache = NULL;
}
+
+ /**
+ *
+ */
+ template <typename T>
+ static bool validateCache(ShaderCache& cache, std::vector<T> hash) {
+ return cache.validateCache(hash.data(), hash.size() * sizeof(T));
+ }
};
} /* namespace skiapipeline */
@@ -75,26 +82,39 @@
return false;
}
-bool checkShader(const sk_sp<SkData>& shader, const char* program) {
- sk_sp<SkData> shader2 = SkData::MakeWithCString(program);
- return shader->size() == shader2->size()
- && 0 == memcmp(shader->data(), shader2->data(), shader->size());
+inline bool
+checkShader(const sk_sp<SkData>& shader1, const sk_sp<SkData>& shader2) {
+ return nullptr != shader1 && nullptr != shader2 && shader1->size() == shader2->size()
+ && 0 == memcmp(shader1->data(), shader2->data(), shader1->size());
}
-bool checkShader(const sk_sp<SkData>& shader, std::vector<char>& program) {
- sk_sp<SkData> shader2 = SkData::MakeWithCopy(program.data(), program.size());
- return shader->size() == shader2->size()
- && 0 == memcmp(shader->data(), shader2->data(), shader->size());
+inline bool
+checkShader(const sk_sp<SkData>& shader, const char* program) {
+ sk_sp<SkData> shader2 = SkData::MakeWithCString(program);
+ return checkShader(shader, shader2);
+}
+
+template <typename T>
+bool checkShader(const sk_sp<SkData>& shader, std::vector<T>& program) {
+ sk_sp<SkData> shader2 = SkData::MakeWithCopy(program.data(), program.size() * sizeof(T));
+ return checkShader(shader, shader2);
}
void setShader(sk_sp<SkData>& shader, const char* program) {
shader = SkData::MakeWithCString(program);
}
-void setShader(sk_sp<SkData>& shader, std::vector<char>& program) {
- shader = SkData::MakeWithCopy(program.data(), program.size());
+template <typename T>
+void setShader(sk_sp<SkData>& shader, std::vector<T>& buffer) {
+ shader = SkData::MakeWithCopy(buffer.data(), buffer.size() * sizeof(T));
}
+template <typename T>
+void genRandomData(std::vector<T>& buffer) {
+ for (auto& data : buffer) {
+ data = T(std::rand());
+ }
+}
#define GrProgramDescTest(a) (*SkData::MakeWithCString(#a).get())
@@ -110,6 +130,7 @@
//remove any test files from previous test run
int deleteFile = remove(cacheFile1.c_str());
ASSERT_TRUE(0 == deleteFile || ENOENT == errno);
+ std::srand(0);
//read the cache from a file that does not exist
ShaderCache::get().setFilename(cacheFile1.c_str());
@@ -158,10 +179,8 @@
//write and read big data chunk (50K)
size_t dataSize = 50*1024;
- std::vector<char> dataBuffer(dataSize);
- for (size_t i = 0; i < dataSize; i++) {
- dataBuffer[0] = dataSize % 256;
- }
+ std::vector<uint8_t> dataBuffer(dataSize);
+ genRandomData(dataBuffer);
setShader(inVS, dataBuffer);
ShaderCache::get().store(GrProgramDescTest(432), *inVS.get());
ShaderCacheTestUtils::terminate(ShaderCache::get(), true);
@@ -173,4 +192,96 @@
remove(cacheFile1.c_str());
}
+TEST(ShaderCacheTest, testCacheValidation) {
+ if (!folderExist(getExternalStorageFolder())) {
+ //don't run the test if external storage folder is not available
+ return;
+ }
+ std::string cacheFile1 = getExternalStorageFolder() + "/shaderCacheTest1";
+ std::string cacheFile2 = getExternalStorageFolder() + "/shaderCacheTest2";
+
+ //remove any test files from previous test run
+ int deleteFile = remove(cacheFile1.c_str());
+ ASSERT_TRUE(0 == deleteFile || ENOENT == errno);
+ std::srand(0);
+
+ //generate identity and read the cache from a file that does not exist
+ ShaderCache::get().setFilename(cacheFile1.c_str());
+ ShaderCacheTestUtils::setSaveDelay(ShaderCache::get(), 0); //disable deferred save
+ std::vector<uint8_t> identity(1024);
+ genRandomData(identity);
+ ShaderCache::get().initShaderDiskCache(identity.data(), identity.size() *
+ sizeof(decltype(identity)::value_type));
+
+ // generate random content in cache and store to disk
+ constexpr size_t numBlob(10);
+ constexpr size_t keySize(1024);
+ constexpr size_t dataSize(50 * 1024);
+
+ std::vector< std::pair<sk_sp<SkData>, sk_sp<SkData>> > blobVec(numBlob);
+ for (auto& blob : blobVec) {
+ std::vector<uint8_t> keyBuffer(keySize);
+ std::vector<uint8_t> dataBuffer(dataSize);
+ genRandomData(keyBuffer);
+ genRandomData(dataBuffer);
+
+ sk_sp<SkData> key, data;
+ setShader(key, keyBuffer);
+ setShader(data, dataBuffer);
+
+ blob = std::make_pair(key, data);
+ ShaderCache::get().store(*key.get(), *data.get());
+ }
+ ShaderCacheTestUtils::terminate(ShaderCache::get(), true);
+
+ // change to a file that does not exist and verify validation fails
+ ShaderCache::get().setFilename(cacheFile2.c_str());
+ ShaderCache::get().initShaderDiskCache();
+ ASSERT_FALSE( ShaderCacheTestUtils::validateCache(ShaderCache::get(), identity) );
+ ShaderCacheTestUtils::terminate(ShaderCache::get(), false);
+
+ // restore the original file and verify validation succeeds
+ ShaderCache::get().setFilename(cacheFile1.c_str());
+ ShaderCache::get().initShaderDiskCache(identity.data(), identity.size() *
+ sizeof(decltype(identity)::value_type));
+ ASSERT_TRUE( ShaderCacheTestUtils::validateCache(ShaderCache::get(), identity) );
+ for (const auto& blob : blobVec) {
+ auto outVS = ShaderCache::get().load(*blob.first.get());
+ ASSERT_TRUE( checkShader(outVS, blob.second) );
+ }
+
+ // generate error identity and verify load fails
+ ShaderCache::get().initShaderDiskCache(identity.data(), -1);
+ for (const auto& blob : blobVec) {
+ ASSERT_EQ( ShaderCache::get().load(*blob.first.get()), sk_sp<SkData>() );
+ }
+ ShaderCache::get().initShaderDiskCache(nullptr, identity.size() *
+ sizeof(decltype(identity)::value_type));
+ for (const auto& blob : blobVec) {
+ ASSERT_EQ( ShaderCache::get().load(*blob.first.get()), sk_sp<SkData>() );
+ }
+
+ // verify the cache validation again after load fails
+ ShaderCache::get().initShaderDiskCache(identity.data(), identity.size() *
+ sizeof(decltype(identity)::value_type));
+ ASSERT_TRUE( ShaderCacheTestUtils::validateCache(ShaderCache::get(), identity) );
+ for (const auto& blob : blobVec) {
+ auto outVS = ShaderCache::get().load(*blob.first.get());
+ ASSERT_TRUE( checkShader(outVS, blob.second) );
+ }
+
+ // generate another identity and verify load fails
+ for (auto& data : identity) {
+ data += std::rand();
+ }
+ ShaderCache::get().initShaderDiskCache(identity.data(), identity.size() *
+ sizeof(decltype(identity)::value_type));
+ for (const auto& blob : blobVec) {
+ ASSERT_EQ( ShaderCache::get().load(*blob.first.get()), sk_sp<SkData>() );
+ }
+
+ ShaderCacheTestUtils::terminate(ShaderCache::get(), false);
+ remove(cacheFile1.c_str());
+}
+
} // namespace
diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
index 2be9311..7c81399 100644
--- a/packages/PackageInstaller/AndroidManifest.xml
+++ b/packages/PackageInstaller/AndroidManifest.xml
@@ -106,6 +106,14 @@
</intent-filter>
</receiver>
+ <receiver android:name=".PackageInstalledReceiver"
+ android:exported="true">
+ <intent-filter android:priority="1">
+ <action android:name="android.intent.action.PACKAGE_ADDED" />
+ <data android:scheme="package" />
+ </intent-filter>
+ </receiver>
+
<activity android:name=".UninstallUninstalling"
android:excludeFromRecents="true"
android:exported="false" />
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java
new file mode 100644
index 0000000..67ac99f
--- /dev/null
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2018 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.packageinstaller;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+/**
+ * Receive new app installed broadcast and notify user new app installed.
+ */
+public class PackageInstalledReceiver extends BroadcastReceiver {
+
+ private static final String TAG = "PackageInstalledReceiver";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // TODO: Add logic to handle new app installed.
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index f1b7eec..ca1b489 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -261,6 +261,12 @@
return mPages.get(0).mColumns;
}
+ public int getNumVisibleTiles() {
+ if (mPages.size() == 0) return 0;
+ TilePage currentPage = mPages.get(getCurrentItem());
+ return currentPage.mRecords.size();
+ }
+
public void startTileReveal(Set<String> tileSpecs, final Runnable postAnimation) {
if (tileSpecs.isEmpty() || mPages.size() < 2 || getScrollX() != 0 || !beginFakeDrag()) {
// Do not start the reveal animation unless there are tiles to animate, multiple
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 2a4bb60..3744d7d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -155,6 +155,7 @@
TouchAnimator.Builder translationYBuilder = new Builder();
if (mQsPanel.getHost() == null) return;
+ if (mQuickQsPanel.getTileLayout().getNumVisibleTiles() < 1) return;
Collection<QSTile> tiles = mQsPanel.getHost().getTiles();
int count = 0;
int[] loc1 = new int[2];
@@ -169,6 +170,7 @@
QSTileLayout tileLayout = mQsPanel.getTileLayout();
mAllViews.add((View) tileLayout);
int height = mQs.getView() != null ? mQs.getView().getMeasuredHeight() : 0;
+ int width = mQs.getView() != null ? mQs.getView().getMeasuredWidth() : 0;
int heightDiff = height - mQs.getHeader().getBottom()
+ mQs.getHeader().getPaddingBottom();
firstPageBuilder.addFloat(tileLayout, "translationY", heightDiff, 0);
@@ -181,7 +183,9 @@
}
final View tileIcon = tileView.getIcon().getIconView();
View view = mQs.getView();
- if (count < mNumQuickTiles && mAllowFancy) {
+
+ // This case: less tiles to animate in small displays.
+ if (count < mQuickQsPanel.getTileLayout().getNumVisibleTiles() && mAllowFancy) {
// Quick tiles.
QSTileView quickTileView = mQuickQsPanel.getTileView(tile);
if (quickTileView == null) continue;
@@ -192,18 +196,26 @@
final int xDiff = loc2[0] - loc1[0];
final int yDiff = loc2[1] - loc1[1];
lastXDiff = loc1[0] - lastX;
- // Move the quick tile right from its location to the new one.
- translationXBuilder.addFloat(quickTileView, "translationX", 0, xDiff);
- translationYBuilder.addFloat(quickTileView, "translationY", 0, yDiff);
- // Counteract the parent translation on the tile. So we have a static base to
- // animate the label position off from.
- //firstPageBuilder.addFloat(tileView, "translationY", mQsPanel.getHeight(), 0);
+ if (count < tileLayout.getNumVisibleTiles()) {
+ // Move the quick tile right from its location to the new one.
+ translationXBuilder.addFloat(quickTileView, "translationX", 0, xDiff);
+ translationYBuilder.addFloat(quickTileView, "translationY", 0, yDiff);
- // Move the real tile from the quick tile position to its final
- // location.
- translationXBuilder.addFloat(tileView, "translationX", -xDiff, 0);
- translationYBuilder.addFloat(tileView, "translationY", -yDiff, 0);
+ // Counteract the parent translation on the tile. So we have a static base to
+ // animate the label position off from.
+ //firstPageBuilder.addFloat(tileView, "translationY", mQsPanel.getHeight(), 0);
+
+ // Move the real tile from the quick tile position to its final
+ // location.
+ translationXBuilder.addFloat(tileView, "translationX", -xDiff, 0);
+ translationYBuilder.addFloat(tileView, "translationY", -yDiff, 0);
+
+ } else { // These tiles disappear when expanding
+ firstPageBuilder.addFloat(quickTileView, "alpha", 1, 0);
+ translationYBuilder.addFloat(quickTileView, "translationY", 0, yDiff);
+ translationXBuilder.addFloat(quickTileView, "translationX", 0, xDiff + width);
+ }
mQuickQsViews.add(tileView.getIconWithBackground());
mAllViews.add(tileView.getIcon());
@@ -218,10 +230,9 @@
final int xDiff = loc2[0] - loc1[0];
final int yDiff = loc2[1] - loc1[1];
- firstPageBuilder.addFloat(tileView, "translationY", heightDiff, 0);
- translationXBuilder.addFloat(tileView, "translationX", -xDiff, 0);
+ firstPageBuilder.addFloat(tileView, "translationY", -heightDiff, 0);
translationYBuilder.addFloat(tileView, "translationY", -yDiff, 0);
- translationYBuilder.addFloat(tileIcon, "translationY", -yDiff, 0);
+ translationXBuilder.addFloat(tileView, "translationX", -xDiff, 0);
mAllViews.add(tileIcon);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 7cb22a3..03febda 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -101,12 +101,7 @@
if (savedInstanceState != null) {
setExpanded(savedInstanceState.getBoolean(EXTRA_EXPANDED));
setListening(savedInstanceState.getBoolean(EXTRA_LISTENING));
- int[] loc = new int[2];
- View edit = view.findViewById(android.R.id.edit);
- edit.getLocationInWindow(loc);
- int x = loc[0] + edit.getWidth() / 2;
- int y = loc[1] + edit.getHeight() / 2;
- mQSCustomizer.setEditLocation(x, y);
+ setEditLocation(view);
mQSCustomizer.restoreInstanceState(savedInstanceState);
}
SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallbacks(this);
@@ -161,15 +156,24 @@
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
+ setEditLocation(getView());
if (newConfig.getLayoutDirection() != mLayoutDirection) {
mLayoutDirection = newConfig.getLayoutDirection();
-
if (mQSAnimator != null) {
mQSAnimator.onRtlChanged();
}
}
}
+ private void setEditLocation(View view) {
+ Log.w(TAG, "I'm changing the location of the button!!!");
+ View edit = view.findViewById(android.R.id.edit);
+ int[] loc = edit.getLocationOnScreen();
+ int x = loc[0] + edit.getWidth() / 2;
+ int y = loc[1] + edit.getHeight() / 2;
+ mQSCustomizer.setEditLocation(x, y);
+ }
+
@Override
public void setContainer(ViewGroup container) {
if (container instanceof NotificationsQuickSettingsContainer) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 3fc258b..762fd75 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -29,6 +29,7 @@
import android.os.Message;
import android.service.quicksettings.Tile;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
@@ -60,6 +61,8 @@
public static final String QS_SHOW_BRIGHTNESS = "qs_show_brightness";
public static final String QS_SHOW_HEADER = "qs_show_header";
+ private static final String TAG = "QSPanel";
+
protected final Context mContext;
protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
protected final View mBrightnessView;
@@ -313,7 +316,7 @@
public void onCollapse() {
if (mCustomizePanel != null && mCustomizePanel.isShown()) {
- mCustomizePanel.hide(mCustomizePanel.getWidth() / 2, mCustomizePanel.getHeight() / 2);
+ mCustomizePanel.hide();
}
}
@@ -480,8 +483,7 @@
public void run() {
if (mCustomizePanel != null) {
if (!mCustomizePanel.isCustomizing()) {
- int[] loc = new int[2];
- v.getLocationInWindow(loc);
+ int[] loc = v.getLocationOnScreen();
int x = loc[0] + v.getWidth() / 2;
int y = loc[1] + v.getHeight() / 2;
mCustomizePanel.show(x, y);
@@ -495,7 +497,7 @@
public void closeDetail() {
if (mCustomizePanel != null && mCustomizePanel.isShown()) {
// Treat this as a detail panel for now, to make things easy.
- mCustomizePanel.hide(mCustomizePanel.getWidth() / 2, mCustomizePanel.getHeight() / 2);
+ mCustomizePanel.hide();
return;
}
showDetail(false, mDetailRecord);
@@ -663,5 +665,7 @@
void setListening(boolean listening);
default void setExpansion(float expansion) {}
+
+ int getNumVisibleTiles();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index 1c50f79..556786a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -18,18 +18,17 @@
import android.content.Context;
import android.content.res.Configuration;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
-import android.widget.Space;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTile.SignalState;
import com.android.systemui.plugins.qs.QSTile.State;
-import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -43,6 +42,7 @@
public class QuickQSPanel extends QSPanel {
public static final String NUM_QUICK_TILES = "sysui_qqs_count";
+ private static final String TAG = "QuickQSPanel";
private boolean mDisabledByPolicy;
private static int mDefaultMaxTiles;
@@ -178,121 +178,95 @@
super.setVisibility(visibility);
}
- private static class HeaderTileLayout extends LinearLayout implements QSTileLayout {
+ private static class HeaderTileLayout extends TileLayout {
- protected final ArrayList<TileRecord> mRecords = new ArrayList<>();
private boolean mListening;
- /** Size of the QS tile (width & height). */
- private int mTileDimensionSize;
public HeaderTileLayout(Context context) {
super(context);
setClipChildren(false);
setClipToPadding(false);
-
- mTileDimensionSize = mContext.getResources().getDimensionPixelSize(
- R.dimen.qs_quick_tile_size);
- updateLayoutParams();
}
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- updateLayoutParams();
+ updateResources();
+ }
+
+ @Override
+ public void onFinishInflate(){
+ updateResources();
}
private void updateLayoutParams() {
- setGravity(Gravity.CENTER);
int width = getResources().getDimensionPixelSize(R.dimen.qs_quick_layout_width);
- LayoutParams lp = new LayoutParams(width, LayoutParams.MATCH_PARENT);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(width, LayoutParams.MATCH_PARENT);
lp.gravity = Gravity.CENTER_HORIZONTAL;
setLayoutParams(lp);
}
- /**
- * Returns {@link LayoutParams} based on the given {@code spaceWidth}. If the width is 0,
- * then we're going to have the space expand to take up as much space as possible. If the
- * width is non-zero, we want the inter-tile spacers to be fixed.
- */
- private LayoutParams generateSpaceLayoutParams() {
- LayoutParams lp = new LayoutParams(0, mTileDimensionSize);
- lp.weight = 1;
- lp.gravity = Gravity.CENTER;
- return lp;
- }
-
- @Override
- public void setListening(boolean listening) {
- if (mListening == listening) return;
- mListening = listening;
- for (TileRecord record : mRecords) {
- record.tile.setListening(this, mListening);
- }
- }
-
- @Override
- public void addTile(TileRecord tile) {
- if (getChildCount() != 0) {
- addView(new Space(mContext), getChildCount(), generateSpaceLayoutParams());
- }
-
- addView(tile.tileView, getChildCount(), generateTileLayoutParams());
- mRecords.add(tile);
- tile.tile.setListening(this, mListening);
- }
-
private LayoutParams generateTileLayoutParams() {
- LayoutParams lp = new LayoutParams(mTileDimensionSize, mTileDimensionSize);
- lp.gravity = Gravity.CENTER;
+ LayoutParams lp = new LayoutParams(mCellWidth, mCellHeight);
return lp;
}
@Override
- public void removeTile(TileRecord tile) {
- int childIndex = getChildIndex(tile.tileView);
- // Remove the tile.
- removeViewAt(childIndex);
- if (getChildCount() != 0) {
- // Remove its spacer as well.
- removeViewAt(childIndex);
- }
- mRecords.remove(tile);
- tile.tile.setListening(this, false);
- }
-
- private int getChildIndex(QSTileView tileView) {
- final int childViewCount = getChildCount();
- for (int i = 0; i < childViewCount; i++) {
- if (getChildAt(i) == tileView) {
- return i;
- }
- }
- return -1;
+ protected void addTileView(TileRecord tile) {
+ addView(tile.tileView, getChildCount(), generateTileLayoutParams());
}
@Override
- public int getOffsetTop(TileRecord tile) {
- return 0;
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ // We only care about clipping on the right side
+ Rect bounds = new Rect(0, 0, r - l, 10000);
+ setClipBounds(bounds);
+
+ calculateColumns();
+
+ for (int i = 0; i < mRecords.size(); i++) {
+ mRecords.get(i).tileView.setVisibility( i < mColumns ? View.VISIBLE : View.GONE);
+ }
+
+ setAccessibilityOrder();
+ layoutTileRecords(mColumns);
}
@Override
public boolean updateResources() {
- // No resources here.
+ mCellWidth = mContext.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size);
+ mCellHeight = mCellWidth;
+
+ updateLayoutParams();
+
return false;
}
- @Override
- public boolean hasOverlappingRendering() {
- return false;
- }
+ private boolean calculateColumns() {
+ int prevNumColumns = mColumns;
+ int maxTiles = mRecords.size();
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- if (hideOverflowingChildren(widthMeasureSpec)) {
- return; // Rely on visibility change to trigger remeasure.
+ if (maxTiles == 0){ // Early return during setup
+ mColumns = 0;
+ return true;
}
+ final int availableWidth = getMeasuredWidth() - getPaddingStart() - getPaddingEnd();
+ final int leftoverWithespace = availableWidth - maxTiles * mCellWidth;
+ final int smallestHorizontalMarginNeeded = leftoverWithespace / (maxTiles - 1);
+
+ if (smallestHorizontalMarginNeeded > 0){
+ mCellMarginHorizontal = smallestHorizontalMarginNeeded;
+ mColumns = maxTiles;
+ } else{
+ mColumns = mCellWidth == 0 ? 1 :
+ Math.min(maxTiles, availableWidth / mCellWidth );
+ mCellMarginHorizontal = (availableWidth - mColumns * mCellWidth) / (mColumns - 1);
+ }
+ return mColumns != prevNumColumns;
+ }
+
+ private void setAccessibilityOrder() {
if (mRecords != null && mRecords.size() > 0) {
View previousView = this;
for (TileRecord record : mRecords) {
@@ -306,31 +280,28 @@
}
}
- /**
- * Hide child views that would otherwise be clipped.
- * @return {@code true} if any child visibilities have changed.
- */
- private boolean hideOverflowingChildren(int widthMeasureSpec) {
- if (getChildCount() == 0) {
- return false;
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // Measure each QS tile.
+ for (TileRecord record : mRecords) {
+ if (record.tileView.getVisibility() == GONE) continue;
+ record.tileView.measure(exactly(mCellWidth), exactly(mCellHeight));
}
- boolean childVisibilityChanged = false;
- int widthRemaining = MeasureSpec.getSize(widthMeasureSpec)
- - getChildAt(0).getMeasuredWidth() - getPaddingStart() - getPaddingEnd();
- for (int i = 2; i < getChildCount(); i += 2) {
- View tileChild = getChildAt(i);
- LayoutParams lp = (LayoutParams) tileChild.getLayoutParams();
- // All Space views have 0 width; only tiles contribute to the total width.
- widthRemaining = widthRemaining
- - tileChild.getMeasuredWidth() - lp.getMarginEnd() - lp.getMarginStart();
- int newVisibility = widthRemaining < 0 ? View.GONE : View.VISIBLE;
- if (tileChild.getVisibility() != newVisibility) {
- tileChild.setVisibility(newVisibility);
- getChildAt(i - 1).setVisibility(newVisibility); // Hide spacer as well.
- childVisibilityChanged = true;
- }
- }
- return childVisibilityChanged;
+
+ int height = mCellHeight;
+ if (height < 0) height = 0;
+
+ setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), height);
+ }
+
+ @Override
+ public int getNumVisibleTiles() {
+ return mColumns;
+ }
+
+ @Override
+ protected int getColumnStart(int column) {
+ return getPaddingStart() + column * (mCellWidth + mCellMarginHorizontal);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 45d63e0..c67165e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -56,6 +56,10 @@
public void addTile(TileRecord tile) {
mRecords.add(tile);
tile.tile.setListening(this, mListening);
+ addTileView(tile);
+ }
+
+ protected void addTileView(TileRecord tile) {
addView(tile.tileView);
}
@@ -120,19 +124,18 @@
return false;
}
- private static int exactly(int size) {
+ protected static int exactly(int size) {
return MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
}
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- final int w = getWidth();
+
+ protected void layoutTileRecords(int numRecords) {
final boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
int row = 0;
int column = 0;
// Layout each QS tile.
- for (int i = 0; i < mRecords.size(); i++, column++) {
+ for (int i = 0; i < numRecords; i++, column++) {
// If we reached the last column available to layout a tile, wrap back to the next row.
if (column == mColumns) {
column = 0;
@@ -147,12 +150,22 @@
}
}
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ layoutTileRecords(mRecords.size());
+ }
+
private int getRowTop(int row) {
return row * (mCellHeight + mCellMarginVertical) + mCellMarginTop;
}
- private int getColumnStart(int column) {
+ protected int getColumnStart(int column) {
return getPaddingStart() + mSidePadding + mCellMarginHorizontal / 2 +
column * (mCellWidth + mCellMarginHorizontal);
}
+
+ @Override
+ public int getNumVisibleTiles() {
+ return mRecords.size();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 2ea15bd..3f7eeb8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -26,6 +26,7 @@
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
@@ -63,6 +64,7 @@
private static final int MENU_RESET = Menu.FIRST;
private static final String EXTRA_QS_CUSTOMIZING = "qs_customizing";
+ private static final String TAG = "QSCustomizer";
private final QSDetailClipper mClipper;
private final LightBarController mLightBarController;
@@ -94,7 +96,7 @@
mToolbar.setNavigationOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- hide((int) v.getX() + v.getWidth() / 2, (int) v.getY() + v.getHeight() / 2);
+ hide();
}
});
mToolbar.setOnMenuItemClickListener(this);
@@ -154,16 +156,20 @@
mQs = qs;
}
+ /** Animate and show QSCustomizer panel.
+ * @param x,y Location on screen of {@code edit} button to determine center of animation.
+ */
public void show(int x, int y) {
if (!isShown) {
- mX = x;
- mY = y;
+ int containerLocation[] = findViewById(R.id.customize_container).getLocationOnScreen();
+ mX = x - containerLocation[0];
+ mY = y - containerLocation[1];
MetricsLogger.visible(getContext(), MetricsProto.MetricsEvent.QS_EDIT);
isShown = true;
mOpening = true;
setTileSpecs();
setVisibility(View.VISIBLE);
- mClipper.animateCircularClip(x, y, true, mExpandAnimationListener);
+ mClipper.animateCircularClip(mX, mY, true, mExpandAnimationListener);
queryTiles();
mNotifQsContainer.setCustomizerAnimating(true);
mNotifQsContainer.setCustomizerShowing(true);
@@ -192,7 +198,7 @@
mTileQueryHelper.queryTiles(mHost);
}
- public void hide(int x, int y) {
+ public void hide() {
if (isShown) {
MetricsLogger.hidden(getContext(), MetricsProto.MetricsEvent.QS_EDIT);
isShown = false;
@@ -278,16 +284,18 @@
});
}
}
-
+ /** @param x,y Location on screen of animation center.
+ */
public void setEditLocation(int x, int y) {
- mX = x;
- mY = y;
+ int containerLocation[] = findViewById(R.id.customize_container).getLocationOnScreen();
+ mX = x - containerLocation[0];
+ mY = y - containerLocation[1];
}
private final Callback mKeyguardCallback = () -> {
if (!isAttachedToWindow()) return;
if (Dependency.get(KeyguardMonitor.class).isShowing() && !mOpening) {
- hide(0, 0);
+ hide();
}
};
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 665c6b7..aa1b303 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1561,7 +1561,6 @@
final String defaultImiId = mSettings.getSelectedInputMethod();
final boolean imeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
buildInputMethodListLocked(!imeSelectedOnBoot /* resetDefaultEnabledIme */);
- resetDefaultImeLocked(mContext);
updateFromSettingsLocked(true);
InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mIPackageManager,
mSettings.getEnabledInputMethodListLocked(), currentUserId,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9b097bf..07f3e17 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1988,6 +1988,14 @@
mRequiredVerifierPackage, null /*finishedReceiver*/,
updateUserIds, instantUserIds);
}
+ // If package installer is defined, notify package installer about new
+ // app installed
+ if (mRequiredInstallerPackage != null) {
+ sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
+ extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND /*flags*/,
+ mRequiredInstallerPackage, null /*finishedReceiver*/,
+ firstUserIds, instantUserIds);
+ }
// Send replaced for users that don't see the package for the first time
if (update) {
diff --git a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
index 9fae43a..82d7ab8 100644
--- a/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
+++ b/services/robotests/src/com/android/server/backup/keyvalue/KeyValueBackupTaskTest.java
@@ -63,6 +63,7 @@
import static org.robolectric.Shadows.shadowOf;
import static org.robolectric.shadow.api.Shadow.extract;
import static org.testng.Assert.fail;
+import static org.testng.Assert.expectThrows;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import static java.util.Collections.emptyList;
@@ -1941,6 +1942,29 @@
task.markCancel();
}
+ @Test
+ public void testHandleCancel_callsMarkCancelAndWaitCancel() throws Exception {
+ TransportMock transportMock = setUpInitializedTransport(mTransport);
+ setUpAgentWithData(PACKAGE_1);
+ KeyValueBackupTask task = spy(createKeyValueBackupTask(transportMock, PACKAGE_1));
+ doNothing().when(task).waitCancel();
+
+ task.handleCancel(true);
+
+ InOrder inOrder = inOrder(task);
+ inOrder.verify(task).markCancel();
+ inOrder.verify(task).waitCancel();
+ }
+
+ @Test
+ public void testHandleCancel_whenCancelAllFalse_throws() throws Exception {
+ TransportMock transportMock = setUpInitializedTransport(mTransport);
+ setUpAgentWithData(PACKAGE_1);
+ KeyValueBackupTask task = createKeyValueBackupTask(transportMock, PACKAGE_1);
+
+ expectThrows(IllegalArgumentException.class, () -> task.handleCancel(false));
+ }
+
private void runTask(KeyValueBackupTask task) {
// Pretend we are not on the main-thread to prevent RemoteCall from complaining
mShadowMainLooper.setCurrentThread(false);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 8703e65..ffbe7d3 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -107,13 +107,34 @@
/**
* Boolean indicating if the "Call barring" item is visible in the Call Settings menu.
- * true means visible. false means gone.
- * @hide
+ * If true, the "Call Barring" menu will be visible. If false, the menu will be gone.
+ *
+ * Disabled by default.
*/
public static final String KEY_CALL_BARRING_VISIBILITY_BOOL =
"call_barring_visibility_bool";
/**
+ * Flag indicating whether or not changing the call barring password via the "Call Barring"
+ * settings menu is supported. If true, the option will be visible in the "Call
+ * Barring" settings menu. If false, the option will not be visible.
+ *
+ * Enabled by default.
+ */
+ public static final String KEY_CALL_BARRING_SUPPORTS_PASSWORD_CHANGE_BOOL =
+ "call_barring_supports_password_change_bool";
+
+ /**
+ * Flag indicating whether or not deactivating all call barring features via the "Call Barring"
+ * settings menu is supported. If true, the option will be visible in the "Call
+ * Barring" settings menu. If false, the option will not be visible.
+ *
+ * Enabled by default.
+ */
+ public static final String KEY_CALL_BARRING_SUPPORTS_DEACTIVATE_ALL_BOOL =
+ "call_barring_supports_deactivate_all_bool";
+
+ /**
* Flag indicating whether the Phone app should ignore EVENT_SIM_NETWORK_LOCKED
* events from the Sim.
* If true, this will prevent the IccNetworkDepersonalizationPanel from being shown, and
@@ -2125,6 +2146,8 @@
sDefaults.putBoolean(KEY_CARRIER_VOLTE_PROVISIONED_BOOL, false);
sDefaults.putBoolean(KEY_CALL_BARRING_VISIBILITY_BOOL, false);
+ sDefaults.putBoolean(KEY_CALL_BARRING_SUPPORTS_PASSWORD_CHANGE_BOOL, true);
+ sDefaults.putBoolean(KEY_CALL_BARRING_SUPPORTS_DEACTIVATE_ALL_BOOL, true);
sDefaults.putBoolean(KEY_CALL_FORWARDING_VISIBILITY_BOOL, true);
sDefaults.putBoolean(KEY_ADDITIONAL_SETTINGS_CALLER_ID_VISIBILITY_BOOL, true);
sDefaults.putBoolean(KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL, true);
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index 3517984..3b9f93e 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -18,14 +18,14 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertFalse;
-import android.os.Parcel;
import android.net.MacAddress;
import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
-import android.net.wifi.WifiInfo;
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
@@ -33,6 +33,7 @@
/**
* Unit tests for {@link android.net.wifi.WifiConfiguration}.
*/
+@SmallTest
public class WifiConfigurationTest {
@Before
diff --git a/wifi/tests/src/android/net/wifi/WifiSsidTest.java b/wifi/tests/src/android/net/wifi/WifiSsidTest.java
index e5794c5..b58f2c7 100644
--- a/wifi/tests/src/android/net/wifi/WifiSsidTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiSsidTest.java
@@ -19,14 +19,16 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import android.support.test.filters.SmallTest;
+
import org.junit.Test;
import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
/**
* Unit tests for {@link android.net.wifi.WifiSsid}.
*/
+@SmallTest
public class WifiSsidTest {
private static final String TEST_SSID = "Test SSID";
diff --git a/wifi/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java b/wifi/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java
index e492475..80f00a4 100644
--- a/wifi/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java
+++ b/wifi/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java
@@ -19,11 +19,14 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import android.support.test.filters.SmallTest;
+
import org.junit.Test;
/**
* Unit test harness for {@link android.net.wifi.p2p.WifiP2pDevice}
*/
+@SmallTest
public class WifiP2pDeviceTest {
/**
diff --git a/wifi/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java b/wifi/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java
index e8e4dc2..2132b41 100644
--- a/wifi/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/p2p/WifiP2pManagerTest.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.os.test.TestLooper;
+import android.support.test.filters.SmallTest;
import libcore.junit.util.ResourceLeakageDetector;
@@ -33,6 +34,7 @@
/**
* Unit test harness for WifiP2pManager.
*/
+@SmallTest
public class WifiP2pManagerTest {
private WifiP2pManager mDut;
private TestLooper mTestLooper;
diff --git a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
index ccb9031..8997ae9 100644
--- a/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/rtt/WifiRttManagerTest.java
@@ -31,6 +31,7 @@
import android.os.IBinder;
import android.os.Parcel;
import android.os.test.TestLooper;
+import android.support.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
@@ -45,6 +46,7 @@
/**
* Unit test harness for WifiRttManager class.
*/
+@SmallTest
public class WifiRttManagerTest {
private WifiRttManager mDut;
private TestLooper mMockLooper;