Merge "Transfer starting windows more aggressively" into pi-dev
diff --git a/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java b/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
index 55b97e7..dc34b7f 100644
--- a/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
@@ -117,6 +117,26 @@
}
@Test
+ public void testNewLayout_RandomText_Selectable() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ BoringLayout.Metrics metrics = new BoringLayout.Metrics();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final TextView textView = new TextView(getContext());
+ textView.setTextIsSelectable(true);
+ textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+ textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+ textView.setText(text);
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.makeNewLayout(TEXT_WIDTH, TEXT_WIDTH, UNKNOWN_BORING, UNKNOWN_BORING,
+ TEXT_WIDTH, false);
+ }
+ }
+
+ @Test
public void testNewLayout_PrecomputedText() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
BoringLayout.Metrics metrics = new BoringLayout.Metrics();
@@ -179,6 +199,24 @@
}
@Test
+ public void testSetText_RandomText_Selectable() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ BoringLayout.Metrics metrics = new BoringLayout.Metrics();
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final TextView textView = new TextView(getContext());
+ textView.setTextIsSelectable(true);
+ textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+ textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.setText(text);
+ }
+ }
+
+ @Test
public void testSetText_PrecomputedText() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
BoringLayout.Metrics metrics = new BoringLayout.Metrics();
@@ -222,8 +260,8 @@
@Test
public void testOnMeasure_RandomText() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
- int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+ int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
while (state.keepRunning()) {
state.pauseTiming();
final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
@@ -240,10 +278,31 @@
}
@Test
+ public void testOnMeasure_RandomText_Selectable() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+ int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final TestableTextView textView = new TestableTextView(getContext());
+ textView.setTextIsSelectable(true);
+ textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+ textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+ textView.setText(text);
+ textView.nullLayouts();
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.onMeasure(width, height);
+ }
+ }
+
+ @Test
public void testOnMeasure_PrecomputedText() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
- int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+ int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
while (state.keepRunning()) {
state.pauseTiming();
final PrecomputedText.Params params = new PrecomputedText.Params.Builder(PAINT)
@@ -265,8 +324,8 @@
@Test
public void testOnMeasure_PrecomputedText_Selectable() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
- int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+ int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
while (state.keepRunning()) {
state.pauseTiming();
final PrecomputedText.Params params = new PrecomputedText.Params.Builder(PAINT)
@@ -289,8 +348,8 @@
@Test
public void testOnDraw_RandomText() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
- int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+ int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
final RenderNode node = RenderNode.create("benchmark", null);
while (state.keepRunning()) {
state.pauseTiming();
@@ -299,8 +358,34 @@
textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
textView.setText(text);
+ textView.measure(width, height);
+ textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
+ final DisplayListCanvas c = node.start(
+ textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
- textView.onMeasure(width, height);
+ Canvas.freeTextLayoutCaches();
+ state.resumeTiming();
+
+ textView.onDraw(c);
+ }
+ }
+
+ @Test
+ public void testOnDraw_RandomText_Selectable() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+ int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ final RenderNode node = RenderNode.create("benchmark", null);
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final TestableTextView textView = new TestableTextView(getContext());
+ textView.setTextIsSelectable(true);
+ textView.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED);
+ textView.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
+ textView.setText(text);
+ textView.measure(width, height);
+ textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
final DisplayListCanvas c = node.start(
textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
@@ -314,8 +399,8 @@
@Test
public void testOnDraw_PrecomputedText() {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
- int width = MeasureSpec.makeMeasureSpec(MeasureSpec.AT_MOST, TEXT_WIDTH);
- int height = MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0);
+ int width = MeasureSpec.makeMeasureSpec(TEXT_WIDTH, MeasureSpec.AT_MOST);
+ int height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
final RenderNode node = RenderNode.create("benchmark", null);
while (state.keepRunning()) {
state.pauseTiming();
@@ -327,8 +412,8 @@
final TestableTextView textView = new TestableTextView(getContext());
textView.setTextMetricsParams(params);
textView.setText(text);
- textView.nullLayouts();
- textView.onMeasure(width, height);
+ textView.measure(width, height);
+ textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
final DisplayListCanvas c = node.start(
textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
@@ -356,8 +441,8 @@
textView.setTextIsSelectable(true);
textView.setTextMetricsParams(params);
textView.setText(text);
- textView.nullLayouts();
- textView.onMeasure(width, height);
+ textView.measure(width, height);
+ textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
final DisplayListCanvas c = node.start(
textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
diff --git a/api/current.txt b/api/current.txt
index 4021ffb..9b492bc 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7278,7 +7278,6 @@
public abstract class SliceProvider extends android.content.ContentProvider {
ctor public SliceProvider();
method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
- method public final java.lang.String getBindingPackage();
method public final java.lang.String getType(android.net.Uri);
method public final android.net.Uri insert(android.net.Uri, android.content.ContentValues);
method public android.app.slice.Slice onBindSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>);
@@ -14437,6 +14436,7 @@
method public static android.graphics.Typeface createFromFile(java.lang.String);
method public static android.graphics.Typeface defaultFromStyle(int);
method public int getStyle();
+ method public int getWeight();
method public final boolean isBold();
method public final boolean isItalic();
field public static final int BOLD = 1; // 0x1
diff --git a/api/system-current.txt b/api/system-current.txt
index 43425cb..d543629 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -6127,19 +6127,24 @@
}
public final class ImsFeatureConfiguration implements android.os.Parcelable {
- ctor public ImsFeatureConfiguration();
method public int describeContents();
- method public int[] getServiceFeatures();
+ method public java.util.Set<android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair> getServiceFeatures();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.telephony.ims.stub.ImsFeatureConfiguration> CREATOR;
}
public static class ImsFeatureConfiguration.Builder {
ctor public ImsFeatureConfiguration.Builder();
- method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int);
+ method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int, int);
method public android.telephony.ims.stub.ImsFeatureConfiguration build();
}
+ public static final class ImsFeatureConfiguration.FeatureSlotPair {
+ ctor public ImsFeatureConfiguration.FeatureSlotPair(int, int);
+ field public final int featureType;
+ field public final int slotId;
+ }
+
public class ImsMultiEndpointImplBase {
ctor public ImsMultiEndpointImplBase();
method public final void onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>);
diff --git a/api/test-current.txt b/api/test-current.txt
index 9d67f4c..54ddd5d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1,3 +1,12 @@
+package android {
+
+ public static final class Manifest.permission {
+ field public static final java.lang.String BRIGHTNESS_SLIDER_USAGE = "android.permission.BRIGHTNESS_SLIDER_USAGE";
+ field public static final java.lang.String CONFIGURE_DISPLAY_BRIGHTNESS = "android.permission.CONFIGURE_DISPLAY_BRIGHTNESS";
+ }
+
+}
+
package android.animation {
public class ValueAnimator extends android.animation.Animator {
diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp
index d0f55ab..f5310a4 100644
--- a/cmds/statsd/src/config/ConfigManager.cpp
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -68,12 +68,25 @@
{
lock_guard <mutex> lock(mMutex);
+ auto it = mConfigs.find(key);
+
+ const int numBytes = config.ByteSize();
+ vector<uint8_t> buffer(numBytes);
+ config.SerializeToArray(&buffer[0], numBytes);
+
+ const bool isDuplicate =
+ it != mConfigs.end() &&
+ StorageManager::hasIdenticalConfig(key, buffer);
+
+ // Update saved file on disk. We still update timestamp of file when
+ // there exists a duplicate configuration to avoid garbage collection.
+ update_saved_configs_locked(key, buffer, numBytes);
+
+ if (isDuplicate) return;
+
// Add to set
mConfigs.insert(key);
- // Save to disk
- update_saved_configs_locked(key, config);
-
for (sp<ConfigListener> listener : mListeners) {
broadcastList.push_back(listener);
}
@@ -137,7 +150,6 @@
{
lock_guard <mutex> lock(mMutex);
-
for (auto it = mConfigs.begin(); it != mConfigs.end();) {
// Remove from map
if (it->GetUid() == uid) {
@@ -230,16 +242,16 @@
}
}
-void ConfigManager::update_saved_configs_locked(const ConfigKey& key, const StatsdConfig& config) {
+void ConfigManager::update_saved_configs_locked(const ConfigKey& key,
+ const vector<uint8_t>& buffer,
+ const int numBytes) {
// If there is a pre-existing config with same key we should first delete it.
remove_saved_configs(key);
// Then we save the latest config.
- string file_name = StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr),
- key.GetUid(), (long long)key.GetId());
- const int numBytes = config.ByteSize();
- vector<uint8_t> buffer(numBytes);
- config.SerializeToArray(&buffer[0], numBytes);
+ string file_name =
+ StringPrintf("%s/%ld_%d_%lld", STATS_SERVICE_DIR, time(nullptr),
+ key.GetUid(), (long long)key.GetId());
StorageManager::writeFile(file_name.c_str(), &buffer[0], numBytes);
}
diff --git a/cmds/statsd/src/config/ConfigManager.h b/cmds/statsd/src/config/ConfigManager.h
index a0c1c1c..9a38188a 100644
--- a/cmds/statsd/src/config/ConfigManager.h
+++ b/cmds/statsd/src/config/ConfigManager.h
@@ -115,7 +115,9 @@
/**
* Save the configs to disk.
*/
- void update_saved_configs_locked(const ConfigKey& key, const StatsdConfig& config);
+ void update_saved_configs_locked(const ConfigKey& key,
+ const std::vector<uint8_t>& buffer,
+ const int numBytes);
/**
* Remove saved configs from disk.
@@ -123,7 +125,7 @@
void remove_saved_configs(const ConfigKey& key);
/**
- * The Configs that have been set. Each config should
+ * Config keys that have been set.
*/
std::set<ConfigKey> mConfigs;
diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp
index 781eced..77387cb 100644
--- a/cmds/statsd/src/storage/StorageManager.cpp
+++ b/cmds/statsd/src/storage/StorageManager.cpp
@@ -245,6 +245,45 @@
}
}
+bool StorageManager::hasIdenticalConfig(const ConfigKey& key,
+ const vector<uint8_t>& config) {
+ unique_ptr<DIR, decltype(&closedir)> dir(opendir(STATS_SERVICE_DIR),
+ closedir);
+ if (dir == NULL) {
+ VLOG("Directory does not exist: %s", STATS_SERVICE_DIR);
+ return false;
+ }
+
+ const char* suffix =
+ StringPrintf("%d_%lld", key.GetUid(), (long long)key.GetId()).c_str();
+
+ dirent* de;
+ while ((de = readdir(dir.get()))) {
+ char* name = de->d_name;
+ if (name[0] == '.') {
+ continue;
+ }
+ size_t nameLen = strlen(name);
+ size_t suffixLen = strlen(suffix);
+ // There can be at most one file that matches this suffix (config key).
+ if (suffixLen <= nameLen &&
+ strncmp(name + nameLen - suffixLen, suffix, suffixLen) == 0) {
+ int fd = open(StringPrintf("%s/%s", STATS_SERVICE_DIR, name).c_str(),
+ O_RDONLY | O_CLOEXEC);
+ if (fd != -1) {
+ string content;
+ if (android::base::ReadFdToString(fd, &content)) {
+ vector<uint8_t> vec(content.begin(), content.end());
+ if (vec == config) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
void StorageManager::trimToFit(const char* path) {
unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir);
if (dir == NULL) {
diff --git a/cmds/statsd/src/storage/StorageManager.h b/cmds/statsd/src/storage/StorageManager.h
index 6c8ed0a..13ce5c6 100644
--- a/cmds/statsd/src/storage/StorageManager.h
+++ b/cmds/statsd/src/storage/StorageManager.h
@@ -78,6 +78,12 @@
* files, accumulation of outdated files.
*/
static void trimToFit(const char* dir);
+
+ /**
+ * Returns true if there already exists identical configuration on device.
+ */
+ static bool hasIdenticalConfig(const ConfigKey& key,
+ const vector<uint8_t>& config);
};
} // namespace statsd
diff --git a/core/java/android/app/servertransaction/TransactionExecutor.java b/core/java/android/app/servertransaction/TransactionExecutor.java
index 9e9a9c5..0d995e8 100644
--- a/core/java/android/app/servertransaction/TransactionExecutor.java
+++ b/core/java/android/app/servertransaction/TransactionExecutor.java
@@ -147,7 +147,10 @@
pw.println("Executor:");
dump(pw, prefix);
- Slog.wtf(TAG, stringWriter.toString());
+ Slog.w(TAG, stringWriter.toString());
+
+ // Ignore requests for non-existent client records for now.
+ return;
}
// Cycle to the state right before the final requested state.
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index df32fb9..aa2cf46 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -16,7 +16,6 @@
package android.app.slice;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.ContentProvider;
@@ -35,7 +34,6 @@
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler;
-import android.os.Looper;
import android.os.Process;
import android.os.StrictMode;
import android.os.StrictMode.ThreadPolicy;
@@ -46,7 +44,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.concurrent.CountDownLatch;
/**
* A SliceProvider allows an app to provide content to be displayed in system spaces. This content
@@ -163,18 +160,10 @@
private static final boolean DEBUG = false;
- private String mBindingPkg;
- private SliceManager mSliceManager;
+ private static final long SLICE_BIND_ANR = 2000;
- /**
- * Return the package name of the caller that initiated the binding request
- * currently happening. The returned package will have been
- * verified to belong to the calling UID. Returns {@code null} if not
- * currently performing an {@link #onBindSlice(Uri, List)}.
- */
- public final @Nullable String getBindingPackage() {
- return mBindingPkg;
- }
+ private String mCallback;
+ private SliceManager mSliceManager;
@Override
public void attachInfo(Context context, ProviderInfo info) {
@@ -183,12 +172,12 @@
}
/**
- * Implemented to create a slice. Will be called on the main thread.
+ * Implemented to create a slice.
* <p>
* onBindSlice should return as quickly as possible so that the UI tied
* to this slice can be responsive. No network or other IO will be allowed
* during onBindSlice. Any loading that needs to be done should happen
- * off the main thread with a call to {@link ContentResolver#notifyChange(Uri, ContentObserver)}
+ * in the background with a call to {@link ContentResolver#notifyChange(Uri, ContentObserver)}
* when the app is ready to provide the complete data in onBindSlice.
* <p>
* The slice returned should have a spec that is compatible with one of
@@ -381,55 +370,32 @@
}
private Collection<Uri> handleGetDescendants(Uri uri) {
- if (Looper.myLooper() == Looper.getMainLooper()) {
+ mCallback = "onGetSliceDescendants";
+ Handler.getMain().postDelayed(mAnr, SLICE_BIND_ANR);
+ try {
return onGetSliceDescendants(uri);
- } else {
- CountDownLatch latch = new CountDownLatch(1);
- Collection<Uri>[] output = new Collection[1];
- Handler.getMain().post(() -> {
- output[0] = onGetSliceDescendants(uri);
- latch.countDown();
- });
- try {
- latch.await();
- return output[0];
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
+ } finally {
+ Handler.getMain().removeCallbacks(mAnr);
}
}
private void handlePinSlice(Uri sliceUri) {
- if (Looper.myLooper() == Looper.getMainLooper()) {
+ mCallback = "onSlicePinned";
+ Handler.getMain().postDelayed(mAnr, SLICE_BIND_ANR);
+ try {
onSlicePinned(sliceUri);
- } else {
- CountDownLatch latch = new CountDownLatch(1);
- Handler.getMain().post(() -> {
- onSlicePinned(sliceUri);
- latch.countDown();
- });
- try {
- latch.await();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
+ } finally {
+ Handler.getMain().removeCallbacks(mAnr);
}
}
private void handleUnpinSlice(Uri sliceUri) {
- if (Looper.myLooper() == Looper.getMainLooper()) {
+ mCallback = "onSliceUnpinned";
+ Handler.getMain().postDelayed(mAnr, SLICE_BIND_ANR);
+ try {
onSliceUnpinned(sliceUri);
- } else {
- CountDownLatch latch = new CountDownLatch(1);
- Handler.getMain().post(() -> {
- onSliceUnpinned(sliceUri);
- latch.countDown();
- });
- try {
- latch.await();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
+ } finally {
+ Handler.getMain().removeCallbacks(mAnr);
}
}
@@ -447,21 +413,12 @@
return createPermissionSlice(getContext(), sliceUri, pkg);
}
}
- if (Looper.myLooper() == Looper.getMainLooper()) {
- return onBindSliceStrict(sliceUri, supportedSpecs, pkg);
- } else {
- CountDownLatch latch = new CountDownLatch(1);
- Slice[] output = new Slice[1];
- Handler.getMain().post(() -> {
- output[0] = onBindSliceStrict(sliceUri, supportedSpecs, pkg);
- latch.countDown();
- });
- try {
- latch.await();
- return output[0];
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
+ mCallback = "onBindSlice";
+ Handler.getMain().postDelayed(mAnr, SLICE_BIND_ANR);
+ try {
+ return onBindSliceStrict(sliceUri, supportedSpecs);
+ } finally {
+ Handler.getMain().removeCallbacks(mAnr);
}
}
@@ -513,19 +470,21 @@
}
}
- private Slice onBindSliceStrict(Uri sliceUri, List<SliceSpec> supportedSpecs,
- String callingPackage) {
+ private Slice onBindSliceStrict(Uri sliceUri, List<SliceSpec> supportedSpecs) {
ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
try {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectAll()
.penaltyDeath()
.build());
- mBindingPkg = callingPackage;
return onBindSlice(sliceUri, supportedSpecs);
} finally {
- mBindingPkg = null;
StrictMode.setThreadPolicy(oldPolicy);
}
}
+
+ private final Runnable mAnr = () -> {
+ Process.sendSignal(Process.myPid(), Process.SIGNAL_QUIT);
+ Log.wtf(TAG, "Timed out while handling slice callback " + mCallback);
+ };
}
diff --git a/core/java/android/net/INetdEventCallback.aidl b/core/java/android/net/INetdEventCallback.aidl
index 1fd9423..1e75bf4 100644
--- a/core/java/android/net/INetdEventCallback.aidl
+++ b/core/java/android/net/INetdEventCallback.aidl
@@ -20,8 +20,9 @@
oneway interface INetdEventCallback {
// Possible addNetdEventCallback callers.
- const int CALLBACK_CALLER_DEVICE_POLICY = 0;
- const int CALLBACK_CALLER_NETWORK_WATCHLIST = 1;
+ const int CALLBACK_CALLER_CONNECTIVITY_SERVICE = 0;
+ const int CALLBACK_CALLER_DEVICE_POLICY = 1;
+ const int CALLBACK_CALLER_NETWORK_WATCHLIST = 2;
/**
* Reports a single DNS lookup function call.
@@ -39,6 +40,18 @@
int uid);
/**
+ * Represents a private DNS validation success or failure.
+ * This method must not block or perform long-running operations.
+ *
+ * @param netId the ID of the network the validation was performed on.
+ * @param ipAddress the IP address for which validation was performed.
+ * @param hostname the hostname for which validation was performed.
+ * @param validated whether or not validation was successful.
+ */
+ void onPrivateDnsValidationEvent(int netId, String ipAddress, String hostname,
+ boolean validated);
+
+ /**
* Reports a single connect library call.
* This method must not block or perform long-running operations.
*
diff --git a/core/java/android/se/omapi/Session.java b/core/java/android/se/omapi/Session.java
index 19a018e..3d8b74b 100644
--- a/core/java/android/se/omapi/Session.java
+++ b/core/java/android/se/omapi/Session.java
@@ -301,12 +301,6 @@
* provide a new logical channel.
*/
public @Nullable Channel openLogicalChannel(byte[] aid, byte p2) throws IOException {
-
- if ((mReader.getName().startsWith("SIM")) && (aid == null)) {
- Log.e(TAG, "NULL AID not supported on " + mReader.getName());
- return null;
- }
-
if (!mService.isConnected()) {
throw new IllegalStateException("service not connected to system");
}
diff --git a/core/java/android/view/RemoteAnimationTarget.java b/core/java/android/view/RemoteAnimationTarget.java
index 75cdd49..5b2cc81 100644
--- a/core/java/android/view/RemoteAnimationTarget.java
+++ b/core/java/android/view/RemoteAnimationTarget.java
@@ -16,13 +16,26 @@
package android.view;
+import static android.app.RemoteAnimationTargetProto.CLIP_RECT;
+import static android.app.RemoteAnimationTargetProto.CONTENT_INSETS;
+import static android.app.RemoteAnimationTargetProto.IS_TRANSLUCENT;
+import static android.app.RemoteAnimationTargetProto.LEASH;
+import static android.app.RemoteAnimationTargetProto.MODE;
+import static android.app.RemoteAnimationTargetProto.POSITION;
+import static android.app.RemoteAnimationTargetProto.PREFIX_ORDER_INDEX;
+import static android.app.RemoteAnimationTargetProto.SOURCE_CONTAINER_BOUNDS;
+import static android.app.RemoteAnimationTargetProto.TASK_ID;
+import static android.app.RemoteAnimationTargetProto.WINDOW_CONFIGURATION;
+
import android.annotation.IntDef;
import android.app.WindowConfiguration;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.proto.ProtoOutputStream;
+import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -164,6 +177,35 @@
dest.writeBoolean(isNotInRecents);
}
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("mode="); pw.print(mode);
+ pw.print(" taskId="); pw.print(taskId);
+ pw.print(" isTranslucent="); pw.print(isTranslucent);
+ pw.print(" clipRect="); clipRect.printShortString(pw);
+ pw.print(" contentInsets="); contentInsets.printShortString(pw);
+ pw.print(" prefixOrderIndex="); pw.print(prefixOrderIndex);
+ pw.print(" position="); position.printShortString(pw);
+ pw.print(" sourceContainerBounds="); sourceContainerBounds.printShortString(pw);
+ pw.println();
+ pw.print(prefix); pw.print("windowConfiguration="); pw.println(windowConfiguration);
+ pw.print(prefix); pw.print("leash="); pw.println(leash);
+ }
+
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ proto.write(TASK_ID, taskId);
+ proto.write(MODE, mode);
+ leash.writeToProto(proto, LEASH);
+ proto.write(IS_TRANSLUCENT, isTranslucent);
+ clipRect.writeToProto(proto, CLIP_RECT);
+ contentInsets.writeToProto(proto, CONTENT_INSETS);
+ proto.write(PREFIX_ORDER_INDEX, prefixOrderIndex);
+ position.writeToProto(proto, POSITION);
+ sourceContainerBounds.writeToProto(proto, SOURCE_CONTAINER_BOUNDS);
+ windowConfiguration.writeToProto(proto, WINDOW_CONFIGURATION);
+ proto.end(token);
+ }
+
public static final Creator<RemoteAnimationTarget> CREATOR
= new Creator<RemoteAnimationTarget>() {
public RemoteAnimationTarget createFromParcel(Parcel in) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bf0e2eb..b624870 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6546,7 +6546,7 @@
} finally {
// Set it to already called so it's not called twice when called by
// performClickInternal()
- mPrivateFlags |= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
+ mPrivateFlags &= ~PFLAG_NOTIFY_AUTOFILL_MANAGER_ON_CLICK;
}
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6fe64a0..f77a6b7 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -291,6 +291,7 @@
* @attr ref android.R.styleable#TextView_drawableTintMode
* @attr ref android.R.styleable#TextView_lineSpacingExtra
* @attr ref android.R.styleable#TextView_lineSpacingMultiplier
+ * @attr ref android.R.styleable#TextView_justificationMode
* @attr ref android.R.styleable#TextView_marqueeRepeatLimit
* @attr ref android.R.styleable#TextView_inputType
* @attr ref android.R.styleable#TextView_imeOptions
diff --git a/core/java/com/android/server/net/BaseNetdEventCallback.java b/core/java/com/android/server/net/BaseNetdEventCallback.java
index 3d3a3d0..fdba2f3 100644
--- a/core/java/com/android/server/net/BaseNetdEventCallback.java
+++ b/core/java/com/android/server/net/BaseNetdEventCallback.java
@@ -32,6 +32,12 @@
}
@Override
+ public void onPrivateDnsValidationEvent(int netId, String ipAddress,
+ String hostname, boolean validated) {
+ // default no-op
+ }
+
+ @Override
public void onConnectEvent(String ipAddr, int port, long timestamp, int uid) {
// default no-op
}
diff --git a/core/proto/android/server/animationadapter.proto b/core/proto/android/server/animationadapter.proto
new file mode 100644
index 0000000..c4ffe8c
--- /dev/null
+++ b/core/proto/android/server/animationadapter.proto
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 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.
+ */
+
+syntax = "proto2";
+
+import "frameworks/base/core/proto/android/graphics/point.proto";
+import "frameworks/base/core/proto/android/view/remote_animation_target.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
+package com.android.server.wm.proto;
+option java_multiple_files = true;
+
+message AnimationAdapterProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional LocalAnimationAdapterProto local = 1;
+ optional RemoteAnimationAdapterWrapperProto remote = 2;
+}
+
+/* represents RemoteAnimationAdapterWrapper */
+message RemoteAnimationAdapterWrapperProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional .android.view.RemoteAnimationTargetProto target = 1;
+}
+
+/* represents LocalAnimationAdapter */
+message LocalAnimationAdapterProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional AnimationSpecProto animation_spec = 1;
+}
+
+message AnimationSpecProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional WindowAnimationSpecProto window = 1;
+ optional MoveAnimationSpecProto move = 2;
+ optional AlphaAnimationSpecProto alpha = 3;
+}
+
+/* represents WindowAnimationSpec */
+message WindowAnimationSpecProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional string animation = 1;
+}
+
+/* represents MoveAnimationSpec*/
+message MoveAnimationSpecProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional .android.graphics.PointProto from = 1;
+ optional .android.graphics.PointProto to = 2;
+ optional int64 duration = 3;
+}
+
+/* represents AlphaAnimationSpec */
+message AlphaAnimationSpecProto {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional float from = 1;
+ optional float to = 2;
+ optional int64 duration = 3;
+}
\ No newline at end of file
diff --git a/core/proto/android/server/surfaceanimator.proto b/core/proto/android/server/surfaceanimator.proto
index 7f7839e..dcc2b34 100644
--- a/core/proto/android/server/surfaceanimator.proto
+++ b/core/proto/android/server/surfaceanimator.proto
@@ -16,6 +16,7 @@
syntax = "proto2";
+import "frameworks/base/core/proto/android/server/animationadapter.proto";
import "frameworks/base/core/proto/android/view/surfacecontrol.proto";
import "frameworks/base/libs/incident/proto/android/privacy.proto";
@@ -28,7 +29,8 @@
message SurfaceAnimatorProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
- optional string animation_adapter = 1;
+ reserved 1; // Was string animation_adapter = 1
optional .android.view.SurfaceControlProto leash = 2;
optional bool animation_start_delayed = 3;
+ optional AnimationAdapterProto animation_adapter = 4;
}
\ No newline at end of file
diff --git a/core/proto/android/view/remote_animation_target.proto b/core/proto/android/view/remote_animation_target.proto
new file mode 100644
index 0000000..d5da0a9
--- /dev/null
+++ b/core/proto/android/view/remote_animation_target.proto
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 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.
+ */
+
+syntax = "proto2";
+option java_package = "android.app";
+option java_multiple_files = true;
+
+package android.view;
+
+import "frameworks/base/core/proto/android/app/window_configuration.proto";
+import "frameworks/base/core/proto/android/graphics/point.proto";
+import "frameworks/base/core/proto/android/graphics/rect.proto";
+import "frameworks/base/core/proto/android/view/surfacecontrol.proto";
+import "frameworks/base/libs/incident/proto/android/privacy.proto";
+
+/** Proto representation for RemoteAnimationTarget.java class. */
+message RemoteAnimationTargetProto {
+ option (android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional int32 task_id = 1;
+ optional int32 mode = 2;
+ optional .android.view.SurfaceControlProto leash = 3;
+ optional bool is_translucent = 4;
+ optional .android.graphics.RectProto clip_rect = 5;
+ optional .android.graphics.RectProto contentInsets = 6;
+ optional int32 prefix_order_index = 7;
+ optional .android.graphics.PointProto position = 8;
+ optional .android.graphics.RectProto source_container_bounds = 9;
+ optional .android.app.WindowConfigurationProto window_configuration = 10;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index f521e4b..a4c0c54 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3089,7 +3089,8 @@
<!-- Allows an application to collect usage infomation about brightness slider changes.
<p>Not for use by third-party applications.</p>
@hide
- @SystemApi -->
+ @SystemApi
+ @TestApi -->
<permission android:name="android.permission.BRIGHTNESS_SLIDER_USAGE"
android:protectionLevel="signature|privileged|development" />
@@ -3102,7 +3103,8 @@
<!-- Allows an application to modify the display brightness configuration
@hide
- @SystemApi -->
+ @SystemApi
+ @TestApi -->
<permission android:name="android.permission.CONFIGURE_DISPLAY_BRIGHTNESS"
android:protectionLevel="signature|privileged|development" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index dc937e6..88dfe42 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -148,16 +148,16 @@
<string name="CLIRPermanent">You can\'t change the caller ID setting.</string>
<!-- Notification title to tell the user that data service is blocked by access control. -->
- <string name="RestrictedOnDataTitle">No data service</string>
+ <string name="RestrictedOnDataTitle">No mobile data service</string>
<!-- Notification title to tell the user that emergency calling is blocked by access control. -->
- <string name="RestrictedOnEmergencyTitle">No emergency calling</string>
+ <string name="RestrictedOnEmergencyTitle">Emergency calling unavailable</string>
<!-- Notification title to tell the user that normal service is blocked by access control. -->
<string name="RestrictedOnNormalTitle">No voice service</string>
<!-- Notification title to tell the user that all emergency and normal voice services are blocked by access control. -->
- <string name="RestrictedOnAllVoiceTitle">No voice/emergency service</string>
+ <string name="RestrictedOnAllVoiceTitle">No voice service or emergency calling</string>
<!-- Notification content to tell the user that voice/data/emergency service is blocked by access control. -->
- <string name="RestrictedStateContent">Temporarily not offered by the mobile network at your location</string>
+ <string name="RestrictedStateContent">Temporarily turned off by your carrier</string>
<!-- Displayed to tell the user that they should switch their network preference. -->
<string name="NetworkPreferenceSwitchTitle">Can\u2019t reach network</string>
@@ -352,9 +352,6 @@
<!-- Work profile deleted notification--> <skip />
<!-- Shows up in the notification's title when the system deletes the work profile. [CHAR LIMIT=NONE] -->
<string name="work_profile_deleted">Work profile deleted</string>
- <!-- Content text for a notification. The Title of the notification is "Work profile deleted".
- This says that the profile is deleted by the system as a result of the current profile owner gone missing. [CHAR LIMIT=100]-->
- <string name="work_profile_deleted_description">Work profile deleted due to missing admin app</string>
<!-- Content text for an expanded notification. The Title of the notification is "Work profile deleted".
This further explains that the profile is deleted by the system as a result of the current profile admin gone missing. [CHAR LIMIT=NONE]-->
<string name="work_profile_deleted_details">The work profile admin app is either missing or corrupted.
diff --git a/core/tests/coretests/AndroidTest.xml b/core/tests/coretests/AndroidTest.xml
index 970a0f0..7b5ad9a 100644
--- a/core/tests/coretests/AndroidTest.xml
+++ b/core/tests/coretests/AndroidTest.xml
@@ -14,15 +14,16 @@
limitations under the License.
-->
<configuration description="Runs Frameworks Core Tests.">
- <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
<option name="test-file-name" value="FrameworksCoreTests.apk" />
<option name="test-file-name" value="BstatsTestApp.apk" />
</target_preparer>
-
- <option name="test-suite-tag" value="apct" />
<option name="test-tag" value="FrameworksCoreTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.frameworks.coretests" />
- <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
</test>
</configuration>
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index f27c11d..20c22b7 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -167,10 +167,8 @@
nativeSetDefault(t.native_instance);
}
- // TODO: Make this public API. (b/64852739)
- /** @hide */
- @VisibleForTesting
- public int getWeight() {
+ /** Returns the typeface's weight value */
+ public @IntRange(from = 0, to = 1000) int getWeight() {
return mWeight;
}
@@ -883,6 +881,15 @@
}
/**
+ * This method is used by supportlib-v27.
+ * TODO: Remove private API use in supportlib: http://b/72665240
+ */
+ private static Typeface createFromFamiliesWithDefault(FontFamily[] families, int weight,
+ int italic) {
+ return createFromFamiliesWithDefault(families, DEFAULT_FAMILY, weight, italic);
+ }
+
+ /**
* Create a new typeface from an array of font families, including
* also the font families in the fallback list.
* @param fallbackName the family name. If given families don't support characters, the
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 2482095..085e112 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -563,8 +563,7 @@
// If there were no scan results, create an AP for the currently connected network (if
// it exists).
- // TODO(sghuman): Investigate if this works for an ephemeral (auto-connected) network
- // when there are no scan results, as it may not have a valid WifiConfiguration
+ // TODO(b/b/73076869): Add support for passpoint (ephemeral) networks
if (accessPoints.isEmpty() && connectionConfig != null) {
AccessPoint activeAp = new AccessPoint(mContext, connectionConfig);
activeAp.update(connectionConfig, mLastInfo, mLastNetworkInfo);
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 54c02a2..e435a72 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -18,9 +18,11 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -50,6 +52,7 @@
import android.text.style.TtsSpan;
import com.android.settingslib.R;
+import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.wifi.AccessPoint.Speed;
import org.junit.Before;
@@ -61,6 +64,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -79,6 +83,8 @@
private Context mContext;
@Mock private RssiCurve mockBadgeCurve;
@Mock private WifiNetworkScoreCache mockWifiNetworkScoreCache;
+ public static final int NETWORK_ID = 123;
+ public static final int DEFAULT_RSSI = -55;
private static ScanResult createScanResult(String ssid, String bssid, int rssi) {
ScanResult scanResult = new ScanResult();
@@ -753,16 +759,15 @@
assertThat(ap.update(config, wifiInfo, newInfo)).isFalse();
}
@Test
- public void testUpdateWithConfigChangeOnly_returnsFalseButInvokesListener() {
- int networkId = 123;
- int rssi = -55;
+ public void testUpdateWithConfigChangeOnly_returnsFalseButInvokesListener()
+ throws InterruptedException {
WifiConfiguration config = new WifiConfiguration();
- config.networkId = networkId;
+ config.networkId = NETWORK_ID;
config.numNoInternetAccessReports = 1;
WifiInfo wifiInfo = new WifiInfo();
- wifiInfo.setNetworkId(networkId);
- wifiInfo.setRssi(rssi);
+ wifiInfo.setNetworkId(NETWORK_ID);
+ wifiInfo.setRssi(DEFAULT_RSSI);
NetworkInfo networkInfo =
new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
@@ -770,8 +775,8 @@
AccessPoint ap = new TestAccessPointBuilder(mContext)
.setNetworkInfo(networkInfo)
- .setNetworkId(networkId)
- .setRssi(rssi)
+ .setNetworkId(NETWORK_ID)
+ .setRssi(DEFAULT_RSSI)
.setWifiInfo(wifiInfo)
.build();
@@ -781,18 +786,131 @@
config.validatedInternetAccess = true;
assertThat(ap.update(newConfig, wifiInfo, networkInfo)).isFalse();
+
+ // Wait for MainHandler to process callback
+ CountDownLatch latch = new CountDownLatch(1);
+ ThreadUtils.postOnMainThread(latch::countDown);
+
+ latch.await();
verify(mockListener).onAccessPointChanged(ap);
}
@Test
- public void testUpdateWithNullWifiConfiguration_doesNotThrowNPE() {
- int networkId = 123;
- int rssi = -55;
+ public void testConnectionInfo_doesNotThrowNPE_ifListenerIsNulledWhileAwaitingExecution()
+ throws InterruptedException {
WifiConfiguration config = new WifiConfiguration();
- config.networkId = networkId;
+ config.networkId = NETWORK_ID;
+ config.numNoInternetAccessReports = 1;
+
WifiInfo wifiInfo = new WifiInfo();
- wifiInfo.setNetworkId(networkId);
- wifiInfo.setRssi(rssi);
+ wifiInfo.setNetworkId(NETWORK_ID);
+ wifiInfo.setRssi(DEFAULT_RSSI);
+
+ NetworkInfo networkInfo =
+ new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+ networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+
+ AccessPoint ap = new TestAccessPointBuilder(mContext)
+ .setNetworkInfo(networkInfo)
+ .setNetworkId(NETWORK_ID)
+ .setRssi(DEFAULT_RSSI)
+ .setWifiInfo(wifiInfo)
+ .build();
+
+ WifiConfiguration newConfig = new WifiConfiguration(config);
+ config.validatedInternetAccess = true;
+
+ performGivenUpdateAndThenNullListenerBeforeResumingMainHandlerExecution(
+ ap, () -> assertThat(ap.update(newConfig, wifiInfo, networkInfo)).isFalse());
+
+ }
+
+ private void performGivenUpdateAndThenNullListenerBeforeResumingMainHandlerExecution(
+ AccessPoint ap, Runnable r) {
+ AccessPoint.AccessPointListener mockListener = mock(AccessPoint.AccessPointListener.class);
+ ap.setListener(mockListener);
+
+ // Put a latch on the MainHandler to prevent the callback from being invoked instantly
+ CountDownLatch latch1 = new CountDownLatch(1);
+ ThreadUtils.postOnMainThread(() -> {
+ try{
+ latch1.await();
+ } catch (InterruptedException e) {
+ fail("Interruped Exception thrown while awaiting latch countdown");
+ }
+ });
+
+ r.run();
+
+ ap.setListener(null);
+ latch1.countDown();
+
+ // The second latch ensures the previously posted listener invocation has processed on the
+ // main thread.
+ CountDownLatch latch2 = new CountDownLatch(1);
+ ThreadUtils.postOnMainThread(latch2::countDown);
+
+ try{
+ latch2.await();
+ } catch (InterruptedException e) {
+ fail("Interruped Exception thrown while awaiting latch countdown");
+ }
+ }
+
+ @Test
+ public void testUpdateScanResults_doesNotThrowNPE_ifListenerIsNulledWhileAwaitingExecution()
+ throws InterruptedException {
+ String ssid = "ssid";
+ int newRssi = -80;
+ AccessPoint ap = new TestAccessPointBuilder(mContext).setSsid(ssid).build();
+
+ ScanResult scanResult = new ScanResult();
+ scanResult.SSID = ssid;
+ scanResult.level = newRssi;
+ scanResult.BSSID = "bssid";
+ scanResult.timestamp = SystemClock.elapsedRealtime() * 1000;
+ scanResult.capabilities = "";
+
+ performGivenUpdateAndThenNullListenerBeforeResumingMainHandlerExecution(
+ ap, () -> ap.setScanResults(Collections.singletonList(scanResult)));
+ }
+
+ @Test
+ public void testUpdateConfig_doesNotThrowNPE_ifListenerIsNulledWhileAwaitingExecution()
+ throws InterruptedException {
+ WifiConfiguration config = new WifiConfiguration();
+ config.networkId = NETWORK_ID;
+ config.numNoInternetAccessReports = 1;
+
+ WifiInfo wifiInfo = new WifiInfo();
+ wifiInfo.setNetworkId(NETWORK_ID);
+ wifiInfo.setRssi(DEFAULT_RSSI);
+
+ NetworkInfo networkInfo =
+ new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+ networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+
+ AccessPoint ap = new TestAccessPointBuilder(mContext)
+ .setNetworkInfo(networkInfo)
+ .setNetworkId(NETWORK_ID)
+ .setRssi(DEFAULT_RSSI)
+ .setWifiInfo(wifiInfo)
+ .build();
+
+ WifiConfiguration newConfig = new WifiConfiguration(config);
+ config.validatedInternetAccess = true;
+
+ performGivenUpdateAndThenNullListenerBeforeResumingMainHandlerExecution(
+ ap, () -> ap.update(newConfig));
+ }
+
+ @Test
+ public void testUpdateWithNullWifiConfiguration_doesNotThrowNPE() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.networkId = NETWORK_ID;
+ WifiInfo wifiInfo = new WifiInfo();
+ wifiInfo.setNetworkId(NETWORK_ID);
+ wifiInfo.setRssi(DEFAULT_RSSI);
NetworkInfo networkInfo =
new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
@@ -800,8 +918,8 @@
AccessPoint ap = new TestAccessPointBuilder(mContext)
.setNetworkInfo(networkInfo)
- .setNetworkId(networkId)
- .setRssi(rssi)
+ .setNetworkId(NETWORK_ID)
+ .setRssi(DEFAULT_RSSI)
.setWifiInfo(wifiInfo)
.build();
@@ -847,34 +965,34 @@
.thenReturn(buildScoredNetworkWithGivenBadgeCurve(badgeCurve2));
ap.update(
- mockWifiNetworkScoreCache, true /* scoringUiEnabled */, MAX_SCORE_CACHE_AGE_MILLIS);
+ mockWifiNetworkScoreCache, true /* scoringUiEnabled */, MAX_SCORE_CACHE_AGE_MILLIS);
assertThat(ap.getSpeed()).isEqualTo(speed1);
}
@Test
public void testSpeedLabelFallbackScoreIgnoresNullCurves() {
- int rssi = -55;
String bssid = "00:00:00:00:00:00";
- int networkId = 123;
WifiInfo info = new WifiInfo();
- info.setRssi(rssi);
+ info.setRssi(DEFAULT_RSSI);
info.setSSID(WifiSsid.createFromAsciiEncoded(TEST_SSID));
info.setBSSID(bssid);
- info.setNetworkId(networkId);
+ info.setNetworkId(NETWORK_ID);
ArrayList<ScanResult> scanResults = new ArrayList<>();
- ScanResult scanResultUnconnected = createScanResult(TEST_SSID, "11:11:11:11:11:11", rssi);
+ ScanResult scanResultUnconnected =
+ createScanResult(TEST_SSID, "11:11:11:11:11:11", DEFAULT_RSSI);
scanResults.add(scanResultUnconnected);
- ScanResult scanResultConnected = createScanResult(TEST_SSID, bssid, rssi);
+ ScanResult scanResultConnected =
+ createScanResult(TEST_SSID, bssid, DEFAULT_RSSI);
scanResults.add(scanResultConnected);
AccessPoint ap =
new TestAccessPointBuilder(mContext)
.setActive(true)
- .setNetworkId(networkId)
+ .setNetworkId(NETWORK_ID)
.setSsid(TEST_SSID)
.setScanResults(scanResults)
.setWifiInfo(info)
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index ca965f3..7fb4dc5 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -721,7 +721,7 @@
// mStaleAccessPoints is true
verify(mockWifiListenerExecutor, never()).onAccessPointsChanged();
- assertThat(tracker.getAccessPoints().size()).isEqualTo(1);
+ assertThat(tracker.getAccessPoints()).hasSize(1);
assertThat(tracker.getAccessPoints().get(0).isActive()).isTrue();
}
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index cce38f1..814b3ef 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -377,6 +377,9 @@
<!-- Content description of the data connection type 3.5G. [CHAR LIMIT=NONE] -->
<string name="data_connection_3_5g">3.5G</string>
+ <!-- Content description of the data connection type 3.5G+. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_3_5g_plus">3.5G+</string>
+
<!-- Content description of the data connection type 4G . [CHAR LIMIT=NONE] -->
<string name="data_connection_4g">4G</string>
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index cad155c..5fce0a6 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -45,6 +45,7 @@
import com.android.systemui.power.PowerNotificationWarnings;
import com.android.systemui.power.PowerUI;
import com.android.systemui.statusbar.AppOpsListener;
+import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
import com.android.systemui.statusbar.phone.LightBarController;
@@ -317,6 +318,8 @@
mProviders.put(AppOpsListener.class, () -> new AppOpsListener(mContext));
+ mProviders.put(VibratorHelper.class, () -> new VibratorHelper(mContext));
+
// Put all dependencies above here so the factory can override them if it wants.
SystemUIFactory.getInstance().injectDependencies(mProviders, mContext);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index ca66e98..0716b37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -55,6 +55,7 @@
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
@@ -912,4 +913,16 @@
return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
}
}
+
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ int bottom = insets.getDisplayCutout() != null
+ ? insets.getDisplayCutout().getSafeInsetBottom() : 0;
+ if (isPaddingRelative()) {
+ setPaddingRelative(getPaddingStart(), getPaddingTop(), getPaddingEnd(), bottom);
+ } else {
+ setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), bottom);
+ }
+ return insets;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index ca5a350..e97fa85 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -50,6 +50,7 @@
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
@@ -246,7 +247,7 @@
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
- mVibratorHelper = new VibratorHelper(context);
+ mVibratorHelper = Dependency.get(VibratorHelper.class);
mConfiguration = new Configuration();
mConfiguration.updateFrom(context.getResources().getConfiguration());
@@ -1035,6 +1036,7 @@
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+ requestApplyInsets();
reorient();
onPluginDisconnected(null); // Create default gesture helper
Dependency.get(PluginManager.class).addPluginListener(this,
@@ -1112,6 +1114,13 @@
pw.println(" }");
}
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ setPadding(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
+ insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
+ return super.onApplyWindowInsets(insets);
+ }
+
private static void dumpButton(PrintWriter pw, String caption, ButtonDispatcher button) {
pw.print(" " + caption + ": ");
if (button == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 3de0a41..7f1e9d0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -38,6 +38,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
import com.android.systemui.DejankUtils;
+import com.android.systemui.Dependency;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingManager;
@@ -207,7 +208,7 @@
mFalsingManager = FalsingManager.getInstance(context);
mNotificationsDragEnabled =
getResources().getBoolean(R.bool.config_enableNotificationShadeDrag);
- mVibratorHelper = new VibratorHelper(context);
+ mVibratorHelper = Dependency.get(VibratorHelper.class);
mVibrateOnOpening = mContext.getResources().getBoolean(
R.bool.config_vibrateOnIconAnimation);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 5c77524..e4f142a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4624,8 +4624,9 @@
!= FingerprintUnlockController.MODE_UNLOCK);
if (mBouncerShowing) {
- mScrimController.transitionTo(
- mIsOccluded ? ScrimState.BOUNCER_OCCLUDED : ScrimState.BOUNCER);
+ final boolean qsExpanded = mQSPanel != null && mQSPanel.isExpanded();
+ mScrimController.transitionTo(mIsOccluded || qsExpanded ?
+ ScrimState.BOUNCER_OCCLUDED : ScrimState.BOUNCER);
} else if (mLaunchCameraOnScreenTurningOn || isInLaunchTransition()) {
mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
} else if (mBrightnessMirrorVisible) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 81641da..3bcfd4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -126,7 +126,7 @@
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
mRipple = new KeyButtonRipple(context, this);
- mVibratorHelper = new VibratorHelper(context);
+ mVibratorHelper = Dependency.get(VibratorHelper.class);
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
setBackground(mRipple);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 487d1c5..a046675 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -205,13 +205,15 @@
}
MobileIconGroup hGroup = TelephonyIcons.THREE_G;
+ MobileIconGroup hPlusGroup = TelephonyIcons.THREE_G;
if (mConfig.hspaDataDistinguishable) {
hGroup = TelephonyIcons.H;
+ hPlusGroup = TelephonyIcons.H_PLUS;
}
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSDPA, hGroup);
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSUPA, hGroup);
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPA, hGroup);
- mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hGroup);
+ mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_HSPAP, hPlusGroup);
if (mConfig.show4gForLte) {
mNetworkToIconLookup.put(TelephonyManager.NETWORK_TYPE_LTE, TelephonyIcons.FOUR_G);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 5363742..2258fa2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -884,6 +884,7 @@
datatype.equals("e") ? TelephonyIcons.E :
datatype.equals("g") ? TelephonyIcons.G :
datatype.equals("h") ? TelephonyIcons.H :
+ datatype.equals("h+") ? TelephonyIcons.H_PLUS :
datatype.equals("lte") ? TelephonyIcons.LTE :
datatype.equals("lte+") ? TelephonyIcons.LTE_PLUS :
datatype.equals("dis") ? TelephonyIcons.DATA_DISABLED :
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
index 986abef..7e6fe02 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
@@ -28,7 +28,6 @@
static final int ICON_G = R.drawable.ic_g_mobiledata;
static final int ICON_E = R.drawable.ic_e_mobiledata;
static final int ICON_H = R.drawable.ic_h_mobiledata;
- // TODO: add logic to insert H+ icon
static final int ICON_H_PLUS = R.drawable.ic_h_plus_mobiledata;
static final int ICON_3G = R.drawable.ic_3g_mobiledata;
static final int ICON_4G = R.drawable.ic_4g_mobiledata;
@@ -135,6 +134,19 @@
TelephonyIcons.ICON_H,
false);
+ static final MobileIconGroup H_PLUS = new MobileIconGroup(
+ "H+",
+ null,
+ null,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH,
+ 0, 0,
+ 0,
+ 0,
+ AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH[0],
+ R.string.data_connection_3_5g_plus,
+ TelephonyIcons.ICON_H_PLUS,
+ false);
+
static final MobileIconGroup FOUR_G = new MobileIconGroup(
"4G",
null,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index 8629799..365a9b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -74,6 +74,17 @@
verifyDataIndicators(TelephonyIcons.ICON_H);
}
+
+ @Test
+ public void testHspaPlusDataIcon() {
+ setupDefaultSignal();
+ updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
+ TelephonyManager.NETWORK_TYPE_HSPAP);
+
+ verifyDataIndicators(TelephonyIcons.ICON_H_PLUS);
+ }
+
+
@Test
public void testWfcNoDataIcon() {
setupDefaultSignal();
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.mk b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.mk
new file mode 100644
index 0000000..d83b30a
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := DisplayCutoutEmulationDouble
+LOCAL_CERTIFICATE := platform
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := DisplayCutoutEmulationDoubleOverlay
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE)
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/AndroidManifest.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/AndroidManifest.xml
new file mode 100644
index 0000000..5d3385d
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<!--
+ ~ Copyright (C) 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.internal.display.cutout.emulation.double"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="android"
+ android:category="com.android.internal.display_cutout_emulation"
+ android:priority="1"/>
+
+ <application android:label="@string/display_cutout_emulation_overlay" android:hasCode="false"/>
+</manifest>
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml
new file mode 100644
index 0000000..ca261f9
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml
@@ -0,0 +1,67 @@
+<!--
+ ~ Copyright (C) 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.
+ -->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- The bounding path of the cutout region of the main built-in display.
+ Must either be empty if there is no cutout region, or a string that is parsable by
+ {@link android.util.PathParser}.
+
+ The path is assumed to be specified in display coordinates with pixel units and in
+ the display's native orientation, with the origin of the coordinate system at the
+ center top of the display.
+
+ To facilitate writing device-independent emulation overlays, the marker `@dp` can be
+ appended after the path string to interpret coordinates in dp instead of px units.
+ Note that a physical cutout should be configured in pixels for the best results.
+ -->
+ <string translatable="false" name="config_mainBuiltInDisplayCutout">
+ M 0,0
+ L -72, 0
+ L -69.9940446283, 20.0595537175
+ C -69.1582133885, 28.4178661152 -65.2, 32.0 -56.8, 32.0
+ L 56.8, 32.0
+ C 65.2, 32.0 69.1582133885, 28.4178661152 69.9940446283, 20.0595537175
+ L 72, 0
+ Z
+ @bottom
+ M 0,0
+ L -72, 0
+ L -69.9940446283, -20.0595537175
+ C -69.1582133885, -28.4178661152 -65.2, -32.0 -56.8, -32.0
+ L 56.8, -32.0
+ C 65.2, -32.0 69.1582133885, -28.4178661152 69.9940446283, -20.0595537175
+ L 72, 0
+ Z
+ @dp
+ </string>
+
+ <!-- Whether the display cutout region of the main built-in display should be forced to
+ black in software (to avoid aliasing or emulate a cutout that is not physically existent).
+ -->
+ <bool name="config_fillMainBuiltInDisplayCutout">true</bool>
+
+ <!-- Height of the status bar -->
+ <dimen name="status_bar_height_portrait">48dp</dimen>
+ <dimen name="status_bar_height_landscape">28dp</dimen>
+ <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
+ <dimen name="quick_qs_offset_height">48dp</dimen>
+ <!-- Total height of QQS (quick_qs_offset_height + 128) -->
+ <dimen name="quick_qs_total_height">176dp</dimen>
+
+</resources>
+
+
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml
new file mode 100644
index 0000000..68c2dcb
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 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.
+ -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <string name="display_cutout_emulation_overlay">Double display cutout</string>
+
+</resources>
+
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 07012d8..d89cc96 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5499,6 +5499,10 @@
// OS: P
SETTINGS_ZONE_PICKER_FIXED_OFFSET = 1357;
+ // Action: notification shade > manage notifications
+ // OS: P
+ ACTION_MANAGE_NOTIFICATIONS = 1358;
+
// ---- End P Constants, all P constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/backup/java/com/android/server/backup/transport/TransportStats.java b/services/backup/java/com/android/server/backup/transport/TransportStats.java
index 4bef81a..bd84782 100644
--- a/services/backup/java/com/android/server/backup/transport/TransportStats.java
+++ b/services/backup/java/com/android/server/backup/transport/TransportStats.java
@@ -32,9 +32,12 @@
void registerConnectionTime(ComponentName transportComponent, long timeMs) {
synchronized (mStatsLock) {
- mTransportStats
- .computeIfAbsent(transportComponent, name -> new Stats())
- .register(timeMs);
+ Stats stats = mTransportStats.get(transportComponent);
+ if (stats == null) {
+ stats = new Stats();
+ mTransportStats.put(transportComponent, stats);
+ }
+ stats.register(timeMs);
}
}
@@ -71,52 +74,49 @@
private static void dumpStats(PrintWriter pw, String prefix, Stats stats) {
pw.println(
String.format(
- Locale.US, "%sAverage connection time: %.2f ms", prefix, stats.mAverage));
- pw.println(String.format(Locale.US, "%sMax connection time: %d ms", prefix, stats.mMax));
- pw.println(String.format(Locale.US, "%sMin connection time: %d ms", prefix, stats.mMin));
- pw.println(String.format(Locale.US, "%sNumber of connections: %d ", prefix, stats.mN));
+ Locale.US, "%sAverage connection time: %.2f ms", prefix, stats.average));
+ pw.println(String.format(Locale.US, "%sMax connection time: %d ms", prefix, stats.max));
+ pw.println(String.format(Locale.US, "%sMin connection time: %d ms", prefix, stats.min));
+ pw.println(String.format(Locale.US, "%sNumber of connections: %d ", prefix, stats.n));
}
public static final class Stats {
public static Stats merge(Stats a, Stats b) {
return new Stats(
- a.mN + b.mN,
- (a.mAverage * a.mN + b.mAverage * b.mN) / (a.mN + b.mN),
- Math.max(a.mMax, b.mMax),
- Math.min(a.mMin, b.mMin));
+ a.n + b.n,
+ (a.average * a.n + b.average * b.n) / (a.n + b.n),
+ Math.max(a.max, b.max),
+ Math.min(a.min, b.min));
}
- public int mN;
- public double mAverage;
- public long mMax;
- public long mMin;
+ public int n;
+ public double average;
+ public long max;
+ public long min;
public Stats() {
- mN = 0;
- mAverage = 0;
- mMax = 0;
- mMin = Long.MAX_VALUE;
- }
-
- private Stats(Stats original) {
- mN = original.mN;
- mAverage = original.mAverage;
- mMax = original.mMax;
- mMin = original.mMin;
+ n = 0;
+ average = 0;
+ max = 0;
+ min = Long.MAX_VALUE;
}
private Stats(int n, double average, long max, long min) {
- mN = n;
- mAverage = average;
- mMax = max;
- mMin = min;
+ this.n = n;
+ this.average = average;
+ this.max = max;
+ this.min = min;
+ }
+
+ private Stats(Stats original) {
+ this(original.n, original.average, original.max, original.min);
}
private void register(long sample) {
- mAverage = (mAverage * mN + sample) / (mN + 1);
- mN++;
- mMax = Math.max(mMax, sample);
- mMin = Math.min(mMin, sample);
+ average = (average * n + sample) / (n + 1);
+ n++;
+ max = Math.max(max, sample);
+ min = Math.min(min, sample);
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c1c68e8..96633da 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5401,11 +5401,12 @@
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
+ final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(bOptions);
final long origId = Binder.clearCallingIdentity();
try {
synchronized (this) {
return mStackSupervisor.startActivityFromRecents(callingPid, callingUid, taskId,
- SafeActivityOptions.fromBundle(bOptions));
+ safeOptions);
}
} finally {
Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index e38be67..8c49472 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1621,12 +1621,6 @@
return;
}
- if (isState(DESTROYED) || (state != DESTROYED && isState(DESTROYING))) {
- // We cannot move backwards from destroyed and destroying states.
- throw new IllegalArgumentException("cannot move back states once destroying"
- + "current:" + mState + " requested:" + state);
- }
-
final ActivityState prev = mState;
mState = state;
@@ -1641,23 +1635,6 @@
if (parent != null) {
parent.onActivityStateChanged(this, state, reason);
}
-
- if (isState(DESTROYING, DESTROYED)) {
- makeFinishingLocked();
-
- // When moving to the destroyed state, immediately destroy the activity in the
- // associated stack. Most paths for finishing an activity will handle an activity's path
- // to destroy through mechanisms such as ActivityStackSupervisor#mFinishingActivities.
- // However, moving to the destroyed state directly (as in the case of an app dying) and
- // marking it as finished will lead to cleanup steps that will prevent later handling
- // from happening.
- if (isState(DESTROYED)) {
- final ActivityStack stack = getStack();
- if (stack != null) {
- stack.activityDestroyedLocked(this, reason);
- }
- }
- }
}
ActivityState getState() {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 2d7520e..c00fc6a 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3811,14 +3811,6 @@
final ActivityState prevState = r.getState();
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);
- // We are already destroying / have already destroyed the activity. Do not continue to
- // modify it. Note that we do not use ActivityRecord#finishing here as finishing is not
- // indicative of destruction (though destruction is indicative of finishing) as finishing
- // can be delayed below.
- if (r.isState(DESTROYING, DESTROYED)) {
- return null;
- }
-
r.setState(FINISHING, "finishCurrentActivityLocked");
final boolean finishingActivityInNonFocusedStack
= r.getStack() != mStackSupervisor.getFocusedStack()
@@ -4037,26 +4029,16 @@
* state to destroy so only the cleanup here is needed.
*
* Note: Call before #removeActivityFromHistoryLocked.
- *
- * @param r The {@link ActivityRecord} to cleanup.
- * @param cleanServices Whether services bound to the {@link ActivityRecord} should also be
- * cleaned up.
- * @param destroy Whether the {@link ActivityRecord} should be destroyed.
- * @param clearProcess Whether the client process should be cleared.
*/
- private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean destroy,
- boolean clearProcess) {
+ private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState) {
onActivityRemovedFromStack(r);
r.deferRelaunchUntilPaused = false;
r.frozenBeforeDestroy = false;
- if (destroy) {
+ if (setState) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (cleaning up)");
r.setState(DESTROYED, "cleanupActivityLocked");
- }
-
- if (clearProcess) {
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + r);
r.app = null;
}
@@ -4271,7 +4253,7 @@
+ ", app=" + (r.app != null ? r.app.processName : "(null)"));
if (r.isState(DESTROYING, DESTROYED)) {
- if (DEBUG_STATES) Slog.v(TAG_STATES, "activity " + r + " already finishing."
+ if (DEBUG_STATES) Slog.v(TAG_STATES, "activity " + r + " already destroying."
+ "skipping request with reason:" + reason);
return false;
}
@@ -4282,8 +4264,7 @@
boolean removedFromHistory = false;
- cleanUpActivityLocked(r, false /* cleanServices */, false /* destroy */,
- false /*clearProcess*/);
+ cleanUpActivityLocked(r, false, false);
final boolean hadApp = r.app != null;
@@ -4380,6 +4361,10 @@
}
}
+ /**
+ * This method is to only be called from the client via binder when the activity is destroyed
+ * AND finished.
+ */
final void activityDestroyedLocked(ActivityRecord record, String reason) {
if (record != null) {
mHandler.removeMessages(DESTROY_TIMEOUT_MSG, record);
@@ -4389,8 +4374,7 @@
if (isInStackLocked(record) != null) {
if (record.isState(DESTROYING, DESTROYED)) {
- cleanUpActivityLocked(record, true /* cleanServices */, false /* destroy */,
- false /*clearProcess*/);
+ cleanUpActivityLocked(record, true, false);
removeActivityFromHistoryLocked(record, reason);
}
}
@@ -4499,8 +4483,7 @@
r.icicle = null;
}
}
- cleanUpActivityLocked(r, true /* cleanServices */, remove /* destroy */,
- true /*clearProcess*/);
+ cleanUpActivityLocked(r, true, true);
if (remove) {
removeActivityFromHistoryLocked(r, "appDied");
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 185897a..abd24e1 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -3375,7 +3375,8 @@
stack.goToSleepIfPossible(false /* shuttingDown */);
} else {
stack.awakeFromSleepingLocked();
- if (isFocusedStack(stack) && !mKeyguardController.isKeyguardLocked()) {
+ if (isFocusedStack(stack)
+ && !mKeyguardController.isKeyguardShowing(display.mDisplayId)) {
// If the keyguard is unlocked - resume immediately.
// It is possible that the display will not be awake at the time we
// process the keyguard going away, which can happen before the sleep token
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index f1a806b..4f31e53 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -102,9 +102,12 @@
/**
- * There are only 2 possible callbacks.
+ * There are only 3 possible callbacks.
*
- * mNetdEventCallbackList[CALLBACK_CALLER_DEVICE_POLICY].
+ * mNetdEventCallbackList[CALLBACK_CALLER_CONNECTIVITY_SERVICE]
+ * Callback registered/unregistered by ConnectivityService.
+ *
+ * mNetdEventCallbackList[CALLBACK_CALLER_DEVICE_POLICY]
* Callback registered/unregistered when logging is being enabled/disabled in DPM
* by the device owner. It's DevicePolicyManager's responsibility to ensure that.
*
@@ -113,6 +116,7 @@
*/
@GuardedBy("this")
private static final int[] ALLOWED_CALLBACK_TYPES = {
+ INetdEventCallback.CALLBACK_CALLER_CONNECTIVITY_SERVICE,
INetdEventCallback.CALLBACK_CALLER_DEVICE_POLICY,
INetdEventCallback.CALLBACK_CALLER_NETWORK_WATCHLIST
};
@@ -212,6 +216,19 @@
@Override
// Called concurrently by multiple binder threads.
// This method must not block or perform long-running operations.
+ public synchronized void onPrivateDnsValidationEvent(int netId,
+ String ipAddress, String hostname, boolean validated)
+ throws RemoteException {
+ for (INetdEventCallback callback : mNetdEventCallbackList) {
+ if (callback != null) {
+ callback.onPrivateDnsValidationEvent(netId, ipAddress, hostname, validated);
+ }
+ }
+ }
+
+ @Override
+ // Called concurrently by multiple binder threads.
+ // This method must not block or perform long-running operations.
public synchronized void onConnectEvent(int netId, int error, int latencyMs, String ipAddr,
int port, int uid) throws RemoteException {
long timestamp = System.currentTimeMillis();
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index aa1f7d95..c1593a7 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -874,7 +874,14 @@
} else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) {
applyRestrictions(muteMedia || muteEverything, usage);
} else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) {
- applyRestrictions(muteSystem || muteEverything, usage);
+ if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
+ // normally DND will only restrict touch sounds, not haptic feedback/vibrations
+ applyRestrictions(muteSystem || muteEverything, usage,
+ AppOpsManager.OP_PLAY_AUDIO);
+ applyRestrictions(false, usage, AppOpsManager.OP_VIBRATE);
+ } else {
+ applyRestrictions(muteSystem || muteEverything, usage);
+ }
} else {
applyRestrictions(muteEverything, usage);
}
@@ -883,18 +890,22 @@
@VisibleForTesting
- protected void applyRestrictions(boolean mute, int usage) {
+ protected void applyRestrictions(boolean mute, int usage, int code) {
final String[] exceptionPackages = null; // none (for now)
- mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, usage,
- mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
- exceptionPackages);
- mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, usage,
+ mAppOps.setRestriction(code, usage,
mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
exceptionPackages);
}
@VisibleForTesting
+ protected void applyRestrictions(boolean mute, int usage) {
+ applyRestrictions(mute, usage, AppOpsManager.OP_VIBRATE);
+ applyRestrictions(mute, usage, AppOpsManager.OP_PLAY_AUDIO);
+ }
+
+
+ @VisibleForTesting
protected void applyZenToRingerMode() {
if (mAudioManager == null) return;
// force the ringer mode into compliance
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 938edb0..c14beef 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -1755,7 +1755,6 @@
}
void showGlobalActionsInternal() {
- sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
if (mGlobalActions == null) {
mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
}
@@ -2680,8 +2679,9 @@
attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
break;
case TYPE_DREAM:
- // Dreams don't have an app window token and can thus not be letterboxed.
- // Hence always let them extend under the cutout.
+ case TYPE_WALLPAPER:
+ // Dreams and wallpapers don't have an app window token and can thus not be
+ // letterboxed. Hence always let them extend under the cutout.
attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
break;
case TYPE_STATUS_BAR:
@@ -4757,7 +4757,7 @@
// It's a system nav bar or a portrait screen; nav bar goes on bottom.
final int top = cutoutSafeUnrestricted.bottom
- getNavigationBarHeight(rotation, uiMode);
- mTmpNavigationFrame.set(0, top, displayWidth, cutoutSafeUnrestricted.bottom);
+ mTmpNavigationFrame.set(0, top, displayWidth, displayFrames.mUnrestricted.bottom);
displayFrames.mStable.bottom = displayFrames.mStableFullscreen.bottom = top;
if (transientNavBarShowing) {
mNavigationBarController.setBarShowingLw(true);
@@ -4780,7 +4780,7 @@
// Landscape screen; nav bar goes to the right.
final int left = cutoutSafeUnrestricted.right
- getNavigationBarWidth(rotation, uiMode);
- mTmpNavigationFrame.set(left, 0, cutoutSafeUnrestricted.right, displayHeight);
+ mTmpNavigationFrame.set(left, 0, displayFrames.mUnrestricted.right, displayHeight);
displayFrames.mStable.right = displayFrames.mStableFullscreen.right = left;
if (transientNavBarShowing) {
mNavigationBarController.setBarShowingLw(true);
@@ -4803,7 +4803,7 @@
// Seascape screen; nav bar goes to the left.
final int right = cutoutSafeUnrestricted.left
+ getNavigationBarWidth(rotation, uiMode);
- mTmpNavigationFrame.set(cutoutSafeUnrestricted.left, 0, right, displayHeight);
+ mTmpNavigationFrame.set(displayFrames.mUnrestricted.left, 0, right, displayHeight);
displayFrames.mStable.left = displayFrames.mStableFullscreen.left = right;
if (transientNavBarShowing) {
mNavigationBarController.setBarShowingLw(true);
@@ -4832,8 +4832,9 @@
mStatusBarLayer = mNavigationBar.getSurfaceLayer();
// And compute the final frame.
mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
- mTmpNavigationFrame, mTmpNavigationFrame, mTmpNavigationFrame, dcf,
- mTmpNavigationFrame, mTmpNavigationFrame, displayFrames.mDisplayCutout);
+ mTmpNavigationFrame, displayFrames.mDisplayCutoutSafe, mTmpNavigationFrame, dcf,
+ mTmpNavigationFrame, displayFrames.mDisplayCutoutSafe,
+ displayFrames.mDisplayCutout);
if (DEBUG_LAYOUT) Slog.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
return mNavigationBarController.checkHiddenLw();
}
@@ -4991,8 +4992,7 @@
df.set(displayFrames.mDock);
pf.set(displayFrames.mDock);
// IM dock windows layout below the nav bar...
- pf.bottom = df.bottom = of.bottom = Math.min(displayFrames.mUnrestricted.bottom,
- displayFrames.mDisplayCutoutSafe.bottom);
+ pf.bottom = df.bottom = of.bottom = displayFrames.mUnrestricted.bottom;
// ...with content insets above the nav bar
cf.bottom = vf.bottom = displayFrames.mStable.bottom;
if (mStatusBar != null && mFocusedWindow == mStatusBar && canReceiveInput(mStatusBar)) {
@@ -5293,27 +5293,48 @@
final int cutoutMode = attrs.layoutInDisplayCutoutMode;
final boolean attachedInParent = attached != null && !layoutInScreen;
+ final boolean requestedHideNavigation =
+ (requestedSysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
// Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in
// the cutout safe zone.
if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
- final Rect displayCutoutSafeExceptMaybeTop = mTmpRect;
- displayCutoutSafeExceptMaybeTop.set(displayFrames.mDisplayCutoutSafe);
+ final Rect displayCutoutSafeExceptMaybeBars = mTmpRect;
+ displayCutoutSafeExceptMaybeBars.set(displayFrames.mDisplayCutoutSafe);
if (layoutInScreen && layoutInsetDecor && !requestedFullscreen
&& cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) {
// At the top we have the status bar, so apps that are
// LAYOUT_IN_SCREEN | LAYOUT_INSET_DECOR but not FULLSCREEN
// already expect that there's an inset there and we don't need to exclude
// the window from that area.
- displayCutoutSafeExceptMaybeTop.top = Integer.MIN_VALUE;
+ displayCutoutSafeExceptMaybeBars.top = Integer.MIN_VALUE;
+ }
+ if (layoutInScreen && layoutInsetDecor && !requestedHideNavigation
+ && cutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT) {
+ // Same for the navigation bar.
+ switch (mNavigationBarPosition) {
+ case NAV_BAR_BOTTOM:
+ displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
+ break;
+ case NAV_BAR_RIGHT:
+ displayCutoutSafeExceptMaybeBars.right = Integer.MAX_VALUE;
+ break;
+ case NAV_BAR_LEFT:
+ displayCutoutSafeExceptMaybeBars.left = Integer.MIN_VALUE;
+ break;
+ }
+ }
+ if (type == TYPE_INPUT_METHOD && mNavigationBarPosition == NAV_BAR_BOTTOM) {
+ // The IME can always extend under the bottom cutout if the navbar is there.
+ displayCutoutSafeExceptMaybeBars.bottom = Integer.MAX_VALUE;
}
// Windows that are attached to a parent and laid out in said parent are already
// avoidingthe cutout according to that parent and don't need to be further constrained.
if (!attachedInParent) {
- pf.intersectUnchecked(displayCutoutSafeExceptMaybeTop);
+ pf.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
}
- // Make sure that NO_LIMITS windows clipped to the display don't extend into the display
- // don't extend under the cutout.
- df.intersectUnchecked(displayCutoutSafeExceptMaybeTop);
+ // Make sure that NO_LIMITS windows clipped to the display don't extend under the
+ // cutout.
+ df.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
}
// Content should never appear in the cutout.
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index b729b6a..285532a 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -720,9 +720,12 @@
private void playChargingStartedSound() {
final boolean enabled = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.CHARGING_SOUNDS_ENABLED, 1) != 0;
+ final boolean dndOff = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
+ == Settings.Global.ZEN_MODE_OFF;
final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.CHARGING_STARTED_SOUND);
- if (enabled && soundPath != null) {
+ if (enabled && dndOff && soundPath != null) {
final Uri soundUri = Uri.parse("file://" + soundPath);
if (soundUri != null) {
final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
diff --git a/services/core/java/com/android/server/wm/AnimationAdapter.java b/services/core/java/com/android/server/wm/AnimationAdapter.java
index 64f77a2..00e3050 100644
--- a/services/core/java/com/android/server/wm/AnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/AnimationAdapter.java
@@ -17,13 +17,15 @@
package com.android.server.wm;
import android.annotation.ColorInt;
-import android.graphics.Point;
+import android.util.proto.ProtoOutputStream;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.animation.Animation;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+import java.io.PrintWriter;
+
/**
* Interface that describes an animation and bridges the animation start to the component
* responsible for running the animation.
@@ -83,4 +85,14 @@
* @return the desired start time of the status bar transition, in uptime millis
*/
long getStatusBarTransitionsStartTime();
+
+ void dump(PrintWriter pw, String prefix);
+
+ default void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ writeToProto(proto);
+ proto.end(token);
+ }
+
+ void writeToProto(ProtoOutputStream proto);
}
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index a180a3a..5c62987 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -16,11 +16,19 @@
package com.android.server.wm;
-import android.view.SurfaceControl;
+import static com.android.server.wm.proto.AlphaAnimationSpecProto.DURATION;
+import static com.android.server.wm.proto.AlphaAnimationSpecProto.FROM;
+import static com.android.server.wm.proto.AlphaAnimationSpecProto.TO;
+import static com.android.server.wm.proto.AnimationSpecProto.ALPHA;
+
import android.graphics.Rect;
+import android.util.proto.ProtoOutputStream;
+import android.view.SurfaceControl;
import com.android.internal.annotations.VisibleForTesting;
+import java.io.PrintWriter;
+
/**
* Utility class for use by a WindowContainer implementation to add "DimLayer" support, that is
* black layers of varying opacity at various Z-levels which create the effect of a Dim.
@@ -334,5 +342,21 @@
+ mFromAlpha;
t.setAlpha(sc, alpha);
}
+
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("from="); pw.print(mFromAlpha);
+ pw.print(" to="); pw.print(mToAlpha);
+ pw.print(" duration="); pw.println(mDuration);
+ }
+
+ @Override
+ public void writeToProtoInner(ProtoOutputStream proto) {
+ final long token = proto.start(ALPHA);
+ proto.write(FROM, mFromAlpha);
+ proto.write(TO, mToAlpha);
+ proto.write(DURATION, mDuration);
+ proto.end(token);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
index 1b41cb8..3f1fde9 100644
--- a/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/LocalAnimationAdapter.java
@@ -16,12 +16,18 @@
package com.android.server.wm;
+import static com.android.server.wm.proto.AnimationAdapterProto.LOCAL;
+import static com.android.server.wm.proto.LocalAnimationAdapterProto.ANIMATION_SPEC;
+
import android.os.SystemClock;
+import android.util.proto.ProtoOutputStream;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+import java.io.PrintWriter;
+
/**
* Animation that can be executed without holding the window manager lock. See
* {@link SurfaceAnimationRunner}.
@@ -74,6 +80,18 @@
return mSpec.calculateStatusBarTransitionStartTime();
}
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ mSpec.dump(pw, prefix);
+ }
+
+ @Override
+ public void writeToProto(ProtoOutputStream proto) {
+ final long token = proto.start(LOCAL);
+ mSpec.writeToProto(proto, ANIMATION_SPEC);
+ proto.end(token);
+ }
+
/**
* Describes how to apply an animation.
*/
@@ -127,5 +145,15 @@
default boolean canSkipFirstFrame() {
return false;
}
+
+ void dump(PrintWriter pw, String prefix);
+
+ default void writeToProto(ProtoOutputStream proto, long fieldId) {
+ final long token = proto.start(fieldId);
+ writeToProtoInner(proto);
+ proto.end(token);
+ }
+
+ void writeToProtoInner(ProtoOutputStream proto);
}
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 39b886d..59bec74 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -23,6 +23,8 @@
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.proto.RemoteAnimationAdapterWrapperProto.TARGET;
+import static com.android.server.wm.proto.AnimationAdapterProto.REMOTE;
import android.app.ActivityManager.TaskSnapshot;
import android.app.WindowConfiguration;
@@ -33,18 +35,21 @@
import android.os.SystemClock;
import android.util.ArraySet;
import android.util.Log;
-import android.util.Slog;
+import android.util.Slog;import android.util.proto.ProtoOutputStream;
import android.util.SparseBooleanArray;
+import android.util.proto.ProtoOutputStream;
import android.view.IRecentsAnimationController;
import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
-import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+
import com.google.android.collect.Sets;
+
+import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
+
import java.io.PrintWriter;
import java.util.ArrayList;
-
/**
* Controls a single instance of the remote driven recents animation. In particular, this allows
* the calling SystemUI to animate the visible task windows as a part of the transition. The remote
@@ -348,6 +353,7 @@
private SurfaceControl mCapturedLeash;
private OnAnimationFinishedCallback mCapturedFinishCallback;
private final boolean mIsRecentTaskInvisible;
+ private RemoteAnimationTarget mTarget;
TaskAnimationAdapter(Task task, boolean isRecentTaskInvisible) {
mTask = task;
@@ -361,10 +367,11 @@
container.getRelativePosition(position);
container.getBounds(bounds);
final WindowState mainWindow = mTask.getTopVisibleAppMainWindow();
- return new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash,
+ mTarget = new RemoteAnimationTarget(mTask.mTaskId, MODE_CLOSING, mCapturedLeash,
!mTask.fillsParent(), mainWindow.mWinAnimator.mLastClipRect,
mainWindow.mContentInsets, mTask.getPrefixOrderIndex(), position, bounds,
mTask.getWindowConfiguration(), mIsRecentTaskInvisible);
+ return mTarget;
}
@Override
@@ -403,6 +410,26 @@
public long getStatusBarTransitionsStartTime() {
return SystemClock.uptimeMillis();
}
+
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.println("task=" + mTask);
+ if (mTarget != null) {
+ pw.print(prefix); pw.println("Target:");
+ mTarget.dump(pw, prefix + " ");
+ } else {
+ pw.print(prefix); pw.println("Target: null");
+ }
+ }
+
+ @Override
+ public void writeToProto(ProtoOutputStream proto) {
+ final long token = proto.start(REMOTE);
+ if (mTarget != null) {
+ mTarget.writeToProto(proto, TARGET);
+ }
+ proto.end(token);
+ }
}
public void dump(PrintWriter pw, String prefix) {
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index 169d65e..d645110 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -16,8 +16,11 @@
package com.android.server.wm;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.proto.AnimationAdapterProto.REMOTE;
+import static com.android.server.wm.proto.RemoteAnimationAdapterWrapperProto.TARGET;
import android.graphics.Point;
import android.graphics.Rect;
@@ -25,16 +28,18 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import android.view.IRemoteAnimationFinishedCallback;
-import android.view.IRemoteAnimationFinishedCallback.Stub;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
+import com.android.internal.util.FastPrintWriter;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
-import java.lang.ref.WeakReference;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.ArrayList;
/**
@@ -104,6 +109,20 @@
}
});
sendRunningRemoteAnimation(true);
+ if (DEBUG_APP_TRANSITIONS) {
+ writeStartDebugStatement();
+ }
+ }
+
+ private void writeStartDebugStatement() {
+ Slog.i(TAG, "Starting remote animation");
+ final StringWriter sw = new StringWriter();
+ final FastPrintWriter pw = new FastPrintWriter(sw);
+ for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+ mPendingAnimations.get(i).dump(pw, "");
+ }
+ pw.close();
+ Slog.i(TAG, sw.toString());
}
private RemoteAnimationTarget[] createAnimations() {
@@ -133,6 +152,7 @@
}
}
sendRunningRemoteAnimation(false);
+ if (DEBUG_APP_TRANSITIONS) Slog.i(TAG, "Finishing remote animation");
}
private void invokeAnimationCancelled() {
@@ -193,6 +213,7 @@
private OnAnimationFinishedCallback mCapturedFinishCallback;
private final Point mPosition = new Point();
private final Rect mStackBounds = new Rect();
+ private RemoteAnimationTarget mTarget;
RemoteAnimationAdapterWrapper(AppWindowToken appWindowToken, Point position,
Rect stackBounds) {
@@ -210,11 +231,12 @@
if (mainWindow == null) {
return null;
}
- return new RemoteAnimationTarget(task.mTaskId, getMode(),
+ mTarget = new RemoteAnimationTarget(task.mTaskId, getMode(),
mCapturedLeash, !mAppWindowToken.fillsParent(),
mainWindow.mWinAnimator.mLastClipRect, mainWindow.mContentInsets,
mAppWindowToken.getPrefixOrderIndex(), mPosition, mStackBounds,
task.getWindowConfiguration(), false /*isNotInRecents*/);
+ return mTarget;
}
private int getMode() {
@@ -275,5 +297,25 @@
return SystemClock.uptimeMillis()
+ mRemoteAnimationAdapter.getStatusBarTransitionDelay();
}
+
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("token="); pw.println(mAppWindowToken);
+ if (mTarget != null) {
+ pw.print(prefix); pw.println("Target:");
+ mTarget.dump(pw, prefix + " ");
+ } else {
+ pw.print(prefix); pw.println("Target: null");
+ }
+ }
+
+ @Override
+ public void writeToProto(ProtoOutputStream proto) {
+ final long token = proto.start(REMOTE);
+ if (mTarget != null) {
+ mTarget.writeToProto(proto, TARGET);
+ }
+ proto.end(token);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 76f5396..c06caaf 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -313,7 +313,9 @@
*/
void writeToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
- proto.write(ANIMATION_ADAPTER, mAnimation != null ? mAnimation.toString() : "null");
+ if (mAnimation != null) {
+ mAnimation.writeToProto(proto, ANIMATION_ADAPTER);
+ }
if (mLeash != null){
mLeash.writeToProto(proto, LEASH);
}
@@ -322,8 +324,18 @@
}
void dump(PrintWriter pw, String prefix) {
- pw.print(prefix); pw.print("mAnimation="); pw.print(mAnimation);
- pw.print(" mLeash="); pw.println(mLeash);
+ pw.print(prefix); pw.print("mLeash="); pw.print(mLeash);
+ if (mAnimationStartDelayed) {
+ pw.print(" mAnimationStartDelayed="); pw.println(mAnimationStartDelayed);
+ } else {
+ pw.println();
+ }
+ pw.print(prefix); pw.println("Animation:");
+ if (mAnimation != null) {
+ mAnimation.dump(pw, prefix + " ");
+ } else {
+ pw.print(prefix); pw.println("null");
+ }
}
/**
diff --git a/services/core/java/com/android/server/wm/WindowAnimationSpec.java b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
index 43fa3d5..a41eba8 100644
--- a/services/core/java/com/android/server/wm/WindowAnimationSpec.java
+++ b/services/core/java/com/android/server/wm/WindowAnimationSpec.java
@@ -19,10 +19,13 @@
import static com.android.server.wm.AnimationAdapter.STATUS_BAR_TRANSITION_DURATION;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_NONE;
+import static com.android.server.wm.proto.AnimationSpecProto.WINDOW;
+import static com.android.server.wm.proto.WindowAnimationSpecProto.ANIMATION;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.SystemClock;
+import android.util.proto.ProtoOutputStream;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.animation.Animation;
@@ -33,6 +36,8 @@
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
+import java.io.PrintWriter;
+
/**
* Animation spec for regular window animations.
*/
@@ -129,6 +134,18 @@
return mCanSkipFirstFrame;
}
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.println(mAnimation);
+ }
+
+ @Override
+ public void writeToProtoInner(ProtoOutputStream proto) {
+ final long token = proto.start(WINDOW);
+ proto.write(ANIMATION, mAnimation.toString());
+ proto.end(token);
+ }
+
/**
* Tries to find a {@link TranslateAnimation} inside the {@code animation}.
*
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f01dc20..297e067 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -113,6 +113,10 @@
import static com.android.server.wm.proto.IdentifierProto.HASH_CODE;
import static com.android.server.wm.proto.IdentifierProto.TITLE;
import static com.android.server.wm.proto.IdentifierProto.USER_ID;
+import static com.android.server.wm.proto.AnimationSpecProto.MOVE;
+import static com.android.server.wm.proto.MoveAnimationSpecProto.DURATION;
+import static com.android.server.wm.proto.MoveAnimationSpecProto.FROM;
+import static com.android.server.wm.proto.MoveAnimationSpecProto.TO;
import static com.android.server.wm.proto.WindowStateProto.ANIMATING_EXIT;
import static com.android.server.wm.proto.WindowStateProto.ANIMATOR;
import static com.android.server.wm.proto.WindowStateProto.ATTRIBUTES;
@@ -4724,5 +4728,21 @@
t.setPosition(leash, mFrom.x + (mTo.x - mFrom.x) * v,
mFrom.y + (mTo.y - mFrom.y) * v);
}
+
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ pw.print(prefix); pw.print("from="); pw.print(mFrom);
+ pw.print(" to="); pw.print(mTo);
+ pw.print(" duration="); pw.println(mDuration);
+ }
+
+ @Override
+ public void writeToProtoInner(ProtoOutputStream proto) {
+ final long token = proto.start(MOVE);
+ mFrom.writeToProto(proto, FROM);
+ mTo.writeToProto(proto, TO);
+ proto.write(DURATION, mDuration);
+ proto.end(token);
+ }
}
}
diff --git a/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java b/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java
new file mode 100644
index 0000000..322db85c
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/transport/TransportStatsTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 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.server.backup.transport;
+
+import static com.android.server.backup.testing.TransportData.backupTransport;
+import static com.android.server.backup.testing.TransportData.d2dTransport;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.ComponentName;
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.backup.transport.TransportStats.Stats;
+import com.android.server.testing.FrameworkRobolectricTestRunner;
+import com.android.server.testing.SystemLoaderPackages;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+@RunWith(FrameworkRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, sdk = 26)
+@SystemLoaderPackages({"com.android.server.backup"})
+@Presubmit
+public class TransportStatsTest {
+ private static final double TOLERANCE = 0.0001;
+
+ private TransportStats mTransportStats;
+ private ComponentName mTransportComponent1;
+ private ComponentName mTransportComponent2;
+
+ @Before
+ public void setUp() throws Exception {
+ mTransportStats = new TransportStats();
+ mTransportComponent1 = backupTransport().getTransportComponent();
+ mTransportComponent2 = d2dTransport().getTransportComponent();
+ }
+
+ @Test
+ public void testRegisterConnectionTime() {
+ mTransportStats.registerConnectionTime(mTransportComponent1, 50L);
+
+ Stats stats = mTransportStats.getStatsForTransport(mTransportComponent1);
+ assertThat(stats.average).isWithin(TOLERANCE).of(50);
+ assertThat(stats.max).isEqualTo(50L);
+ assertThat(stats.min).isEqualTo(50L);
+ assertThat(stats.n).isEqualTo(1);
+ }
+
+ @Test
+ public void testRegisterConnectionTime_whenHasAlreadyOneSample() {
+ mTransportStats.registerConnectionTime(mTransportComponent1, 50L);
+
+ mTransportStats.registerConnectionTime(mTransportComponent1, 100L);
+
+ Stats stats = mTransportStats.getStatsForTransport(mTransportComponent1);
+ assertThat(stats.average).isWithin(TOLERANCE).of(75);
+ assertThat(stats.max).isEqualTo(100L);
+ assertThat(stats.min).isEqualTo(50L);
+ assertThat(stats.n).isEqualTo(2);
+ }
+
+ @Test
+ public void testGetStatsForTransport() {
+ mTransportStats.registerConnectionTime(mTransportComponent1, 10L);
+ mTransportStats.registerConnectionTime(mTransportComponent2, 20L);
+
+ Stats stats = mTransportStats.getStatsForTransport(mTransportComponent1);
+
+ assertThat(stats.average).isWithin(TOLERANCE).of(10);
+ assertThat(stats.max).isEqualTo(10L);
+ assertThat(stats.min).isEqualTo(10L);
+ assertThat(stats.n).isEqualTo(1);
+ }
+
+ @Test
+ public void testMerge() {
+ mTransportStats.registerConnectionTime(mTransportComponent1, 10L);
+ mTransportStats.registerConnectionTime(mTransportComponent2, 20L);
+ Stats stats1 = mTransportStats.getStatsForTransport(mTransportComponent1);
+ Stats stats2 = mTransportStats.getStatsForTransport(mTransportComponent2);
+
+ Stats stats = Stats.merge(stats1, stats2);
+
+ assertThat(stats.average).isWithin(TOLERANCE).of(15);
+ assertThat(stats.max).isEqualTo(20L);
+ assertThat(stats.min).isEqualTo(10L);
+ assertThat(stats.n).isEqualTo(2);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index ac212ddc..03e870a 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -222,35 +222,4 @@
verify(mService.mStackSupervisor, times(1)).canPlaceEntityOnDisplay(anyInt(), eq(expected),
anyInt(), anyInt(), eq(record.info));
}
-
- @Test
- public void testFinishingAfterDestroying() throws Exception {
- assertFalse(mActivity.finishing);
- mActivity.setState(DESTROYING, "testFinishingAfterDestroying");
- assertTrue(mActivity.isState(DESTROYING));
- assertTrue(mActivity.finishing);
- }
-
- @Test
- public void testFinishingAfterDestroyed() throws Exception {
- assertFalse(mActivity.finishing);
- mActivity.setState(DESTROYED, "testFinishingAfterDestroyed");
- assertTrue(mActivity.isState(DESTROYED));
- assertTrue(mActivity.finishing);
- }
-
- @Test
- public void testSetInvalidState() throws Exception {
- mActivity.setState(DESTROYED, "testInvalidState");
-
- boolean exceptionEncountered = false;
-
- try {
- mActivity.setState(FINISHING, "testInvalidState");
- } catch (IllegalArgumentException e) {
- exceptionEncountered = true;
- }
-
- assertTrue(exceptionEncountered);
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
index bda68d1..f17bfa4 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
@@ -479,28 +479,6 @@
}
@Test
- public void testSuppressMultipleDestroy() throws Exception {
- final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
- final ClientLifecycleManager lifecycleManager = mock(ClientLifecycleManager.class);
- final ProcessRecord app = r.app;
-
- // The mocked lifecycle manager must be set on the ActivityStackSupervisor's reference to
- // the service rather than mService as mService is a spy and setting the value will not
- // propagate as ActivityManagerService hands its own reference to the
- // ActivityStackSupervisor during construction.
- ((TestActivityManagerService) mSupervisor.mService).setLifecycleManager(lifecycleManager);
-
- mStack.destroyActivityLocked(r, true, "first invocation");
- verify(lifecycleManager, times(1)).scheduleTransaction(eq(app.thread),
- eq(r.appToken), any(DestroyActivityItem.class));
- assertTrue(r.isState(DESTROYED, DESTROYING));
-
- mStack.destroyActivityLocked(r, true, "second invocation");
- verify(lifecycleManager, times(1)).scheduleTransaction(eq(app.thread),
- eq(r.appToken), any(DestroyActivityItem.class));
- }
-
- @Test
public void testFinishDisabledPackageActivities() throws Exception {
final ActivityRecord firstActivity = new ActivityBuilder(mService).setTask(mTask).build();
final ActivityRecord secondActivity = new ActivityBuilder(mService).setTask(mTask).build();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 9008803..be58fd2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -35,6 +35,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -160,6 +161,26 @@
}
@Test
+ public void testTotalSilence() {
+ mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
+ mZenModeHelperSpy.applyRestrictions();
+
+ // Total silence will silence alarms, media and system noises (but not vibrations)
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_ALARM);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_MEDIA);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_GAME);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_PLAY_AUDIO);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
+ AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_VIBRATE);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
+ AudioAttributes.USAGE_UNKNOWN);
+ }
+
+ @Test
public void testAlarmsOnly_alarmMediaMuteNotApplied() {
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_ALARMS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
@@ -179,9 +200,9 @@
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
AudioAttributes.USAGE_GAME);
- // Alarms only will silence system noises
+ // Alarms only will silence system noises (but not vibrations)
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
- AudioAttributes.USAGE_ASSISTANCE_SONIFICATION);
+ AudioAttributes.USAGE_ASSISTANCE_SONIFICATION, AppOpsManager.OP_PLAY_AUDIO);
verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
AudioAttributes.USAGE_UNKNOWN);
}
@@ -228,6 +249,7 @@
@Test
public void testZenAllCannotBypass() {
// Only audio attributes with SUPPRESIBLE_NEVER can bypass
+ // with special case USAGE_ASSISTANCE_SONIFICATION
mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
mZenModeHelperSpy.mConfig.allowAlarms = false;
mZenModeHelperSpy.mConfig.allowMedia = false;
@@ -247,9 +269,17 @@
mZenModeHelperSpy.applyRestrictions();
for (int usage : AudioAttributes.SDK_USAGES) {
- boolean shouldMute = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage)
- != AudioAttributes.SUPPRESSIBLE_NEVER;
- verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(shouldMute, usage);
+ if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
+ // only mute audio, not vibrations
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, usage,
+ AppOpsManager.OP_PLAY_AUDIO);
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false, usage,
+ AppOpsManager.OP_VIBRATE);
+ } else {
+ boolean shouldMute = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage)
+ != AudioAttributes.SUPPRESSIBLE_NEVER;
+ verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(shouldMute, usage);
+ }
}
}
diff --git a/telephony/java/android/telephony/NetworkScan.java b/telephony/java/android/telephony/NetworkScan.java
index 7f43ee5..073c313 100644
--- a/telephony/java/android/telephony/NetworkScan.java
+++ b/telephony/java/android/telephony/NetworkScan.java
@@ -115,6 +115,8 @@
telephony.stopNetworkScan(mSubId, mScanId);
} catch (RemoteException ex) {
Rlog.e(TAG, "stopNetworkScan RemoteException", ex);
+ } catch (RuntimeException ex) {
+ Rlog.e(TAG, "stopNetworkScan RuntimeException", ex);
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 22795b1..7add893 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5351,6 +5351,23 @@
}
/**
+ * @return true if the IMS resolver is busy resolving a binding and should not be considered
+ * available, false if the IMS resolver is idle.
+ * @hide
+ */
+ public boolean isResolvingImsBinding() {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.isResolvingImsBinding();
+ }
+ } catch (RemoteException e) {
+ Rlog.e(TAG, "isResolvingImsBinding, RemoteException: " + e.getMessage());
+ }
+ return false;
+ }
+
+ /**
* Set IMS registration state
*
* @param Registration state
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index 946cecf..99e2db8 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -145,7 +145,8 @@
break;
case CALLBACK_SCAN_ERROR:
try {
- executor.execute(() -> callback.onError(message.arg1));
+ final int errorCode = message.arg1;
+ executor.execute(() -> callback.onError(errorCode));
} catch (Exception e) {
Rlog.e(TAG, "Exception in networkscan callback onError", e);
}
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index 2748cb5..c008711 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -161,11 +161,6 @@
}
@Override
- public void notifyImsFeatureReady(int slotId, int featureType) {
- ImsService.this.notifyImsFeatureReady(slotId, featureType);
- }
-
- @Override
public IImsConfig getConfig(int slotId) {
ImsConfigImplBase c = ImsService.this.getConfig(slotId);
return c != null ? c.getIImsConfig() : null;
@@ -274,25 +269,6 @@
}
}
- private void notifyImsFeatureReady(int slotId, int featureType) {
- synchronized (mFeaturesBySlot) {
- // get ImsFeature associated with the slot/feature
- SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
- if (features == null) {
- Log.w(LOG_TAG, "Can not notify ImsFeature ready. No ImsFeatures exist on " +
- "slot " + slotId);
- return;
- }
- ImsFeature f = features.get(featureType);
- if (f == null) {
- Log.w(LOG_TAG, "Can not notify ImsFeature ready. No feature with type "
- + featureType + " exists on slot " + slotId);
- return;
- }
- f.onFeatureReady();
- }
- }
-
/**
* When called, provide the {@link ImsFeatureConfiguration} that this {@link ImsService}
* currently supports. This will trigger the framework to set up the {@link ImsFeature}s that
diff --git a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
index 86f8606..c7da681 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
@@ -36,8 +36,6 @@
ImsFeatureConfiguration querySupportedImsFeatures();
// Synchronous call to ensure the ImsService is ready before continuing with feature creation.
void notifyImsServiceReadyForFeatureCreation();
- // Synchronous call to ensure the new ImsFeature is ready before using the Feature.
- void notifyImsFeatureReady(int slotId, int featureType);
void removeImsFeature(int slotId, int featureType, in IImsFeatureStatusCallback c);
IImsConfig getConfig(int slotId);
IImsRegistration getRegistration(int slotId);
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 2fffd36..c073d1a 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -575,7 +575,7 @@
*/
public ImsUtImplBase getUt() {
// Base Implementation - Should be overridden
- return null;
+ return new ImsUtImplBase();
}
/**
@@ -584,7 +584,7 @@
*/
public ImsEcbmImplBase getEcbm() {
// Base Implementation - Should be overridden
- return null;
+ return new ImsEcbmImplBase();
}
/**
@@ -593,7 +593,7 @@
*/
public ImsMultiEndpointImplBase getMultiEndpoint() {
// Base Implementation - Should be overridden
- return null;
+ return new ImsMultiEndpointImplBase();
}
/**
diff --git a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
index 98b67c3..2f52c0a 100644
--- a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
+++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
@@ -21,6 +21,7 @@
import android.os.Parcelable;
import android.telephony.ims.feature.ImsFeature;
import android.util.ArraySet;
+import android.util.Pair;
import java.util.Set;
@@ -34,14 +35,57 @@
*/
@SystemApi
public final class ImsFeatureConfiguration implements Parcelable {
+
+ public static final class FeatureSlotPair {
+ /**
+ * SIM slot that this feature is associated with.
+ */
+ public final int slotId;
+ /**
+ * The feature that this slotId supports. Supported values are
+ * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+ * {@link ImsFeature#FEATURE_RCS}.
+ */
+ public final @ImsFeature.FeatureType int featureType;
+
+ /**
+ * A mapping from slotId to IMS Feature type.
+ * @param slotId the SIM slot ID associated with this feature.
+ * @param featureType The feature that this slotId supports. Supported values are
+ * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+ * {@link ImsFeature#FEATURE_RCS}.
+ */
+ public FeatureSlotPair(int slotId, @ImsFeature.FeatureType int featureType) {
+ this.slotId = slotId;
+ this.featureType = featureType;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ FeatureSlotPair that = (FeatureSlotPair) o;
+
+ if (slotId != that.slotId) return false;
+ return featureType == that.featureType;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = slotId;
+ result = 31 * result + featureType;
+ return result;
+ }
+ }
+
/**
* Features that this ImsService supports.
*/
- private final Set<Integer> mFeatures;
+ private final Set<FeatureSlotPair> mFeatures;
/**
- * Builder for {@link ImsFeatureConfiguration} that makes adding supported {@link ImsFeature}s
- * easier.
+ * Builder for {@link ImsFeatureConfiguration}.
*/
public static class Builder {
ImsFeatureConfiguration mConfig;
@@ -50,12 +94,15 @@
}
/**
- * @param feature A feature defined in {@link ImsFeature.FeatureType} that this service
- * supports.
+ * Adds an IMS feature associated with a SIM slot ID.
+ * @param slotId The slot ID associated with the IMS feature.
+ * @param featureType The feature that the slot ID supports. Supported values are
+ * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+ * {@link ImsFeature#FEATURE_RCS}.
* @return a {@link Builder} to continue constructing the ImsFeatureConfiguration.
*/
- public Builder addFeature(@ImsFeature.FeatureType int feature) {
- mConfig.addFeature(feature);
+ public Builder addFeature(int slotId, @ImsFeature.FeatureType int featureType) {
+ mConfig.addFeature(slotId, featureType);
return this;
}
@@ -66,8 +113,7 @@
/**
* Creates with all registration features empty.
- *
- * Consider using the provided {@link Builder} to create this configuration instead.
+ * @hide
*/
public ImsFeatureConfiguration() {
mFeatures = new ArraySet<>();
@@ -76,45 +122,41 @@
/**
* Configuration of the ImsService, which describes which features the ImsService supports
* (for registration).
- * @param features an array of feature integers defined in {@link ImsFeature} that describe
- * which features this ImsService supports. Supported values are
- * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
- * {@link ImsFeature#FEATURE_RCS}.
+ * @param features a set of {@link FeatureSlotPair}s that describe which features this
+ * ImsService supports.
* @hide
*/
- public ImsFeatureConfiguration(int[] features) {
+ public ImsFeatureConfiguration(Set<FeatureSlotPair> features) {
mFeatures = new ArraySet<>();
if (features != null) {
- for (int i : features) {
- mFeatures.add(i);
- }
+ mFeatures.addAll(features);
}
}
/**
- * @return an int[] containing the features that this ImsService supports. Supported values are
- * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
- * {@link ImsFeature#FEATURE_RCS}.
+ * @return a set of supported slot ID to feature type pairs contained within a
+ * {@link FeatureSlotPair}.
*/
- public int[] getServiceFeatures() {
- return mFeatures.stream().mapToInt(i->i).toArray();
+ public Set<FeatureSlotPair> getServiceFeatures() {
+ return new ArraySet<>(mFeatures);
}
- void addFeature(int feature) {
- mFeatures.add(feature);
+ /**
+ * @hide
+ */
+ void addFeature(int slotId, int feature) {
+ mFeatures.add(new FeatureSlotPair(slotId, feature));
}
/** @hide */
protected ImsFeatureConfiguration(Parcel in) {
- int[] features = in.createIntArray();
- if (features != null) {
- mFeatures = new ArraySet<>(features.length);
- for(Integer i : features) {
- mFeatures.add(i);
- }
- } else {
- mFeatures = new ArraySet<>();
+ int featurePairLength = in.readInt();
+ // length
+ mFeatures = new ArraySet<>(featurePairLength);
+ for (int i = 0; i < featurePairLength; i++) {
+ // pair of reads for each entry (slotId->featureType)
+ mFeatures.add(new FeatureSlotPair(in.readInt(), in.readInt()));
}
}
@@ -138,7 +180,15 @@
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeIntArray(mFeatures.stream().mapToInt(i->i).toArray());
+ FeatureSlotPair[] featureSlotPairs = new FeatureSlotPair[mFeatures.size()];
+ mFeatures.toArray(featureSlotPairs);
+ // length of list
+ dest.writeInt(featureSlotPairs.length);
+ // then pairs of integers for each entry (slotId->featureType).
+ for (FeatureSlotPair featureSlotPair : featureSlotPairs) {
+ dest.writeInt(featureSlotPair.slotId);
+ dest.writeInt(featureSlotPair.featureType);
+ }
}
/**
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 4002d3c..afbb947 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -829,6 +829,12 @@
boolean isEmergencyMmTelAvailable(int slotId);
/**
+ * @return true if the IMS resolver is busy resolving a binding and should not be considered
+ * available, false if the IMS resolver is idle.
+ */
+ boolean isResolvingImsBinding();
+
+ /**
* Set the network selection mode to automatic.
*
* @param subId the id of the subscription to update.
diff --git a/wifi/java/android/net/wifi/rtt/RangingResult.java b/wifi/java/android/net/wifi/rtt/RangingResult.java
index 936a1f2..4705e1d 100644
--- a/wifi/java/android/net/wifi/rtt/RangingResult.java
+++ b/wifi/java/android/net/wifi/rtt/RangingResult.java
@@ -189,7 +189,8 @@
}
/**
- * @return The Location Configuration Information (LCI) as self-reported by the peer.
+ * @return The Location Configuration Information (LCI) as self-reported by the peer. The format
+ * is specified in the IEEE 802.11-2016 specifications, section 9.4.2.22.10.
* <p>
* Note: the information is NOT validated - use with caution. Consider validating it with
* other sources of information before using it.
@@ -207,7 +208,8 @@
}
/**
- * @return The Location Civic report (LCR) as self-reported by the peer.
+ * @return The Location Civic report (LCR) as self-reported by the peer. The format
+ * is specified in the IEEE 802.11-2016 specifications, section 9.4.2.22.13.
* <p>
* Note: the information is NOT validated - use with caution. Consider validating it with
* other sources of information before using it.