Merge "Update Rail Data Collection Frequency" into qt-dev
diff --git a/Android.mk b/Android.mk
index c58f7af..9bda2dc 100644
--- a/Android.mk
+++ b/Android.mk
@@ -32,27 +32,6 @@
# ============================================================
include $(CLEAR_VARS)
-aidl_parcelables :=
-define stubs-to-aidl-parcelables
- gen := $(TARGET_OUT_COMMON_INTERMEDIATES)/$1.aidl
- aidl_parcelables += $$(gen)
- $$(gen): $(call java-lib-header-files,$1) $(HOST_OUT_EXECUTABLES)/sdkparcelables
- @echo Extract SDK parcelables: $$@
- rm -f $$@
- $(HOST_OUT_EXECUTABLES)/sdkparcelables $$< $$@
-endef
-
-$(foreach stubs,android_stubs_current android_test_stubs_current android_system_stubs_current,\
- $(eval $(call stubs-to-aidl-parcelables,$(stubs))))
-
-gen := $(TARGET_OUT_COMMON_INTERMEDIATES)/framework.aidl
-.KATI_RESTAT: $(gen)
-$(gen): $(aidl_parcelables)
- @echo Combining SDK parcelables: $@
- rm -f $@.tmp
- cat $^ | sort -u > $@.tmp
- $(call commit-change-for-toc,$@)
-
# This is used by ide.mk as the list of source files that are
# always included.
INTERNAL_SDK_SOURCE_DIRS := $(addprefix $(LOCAL_PATH)/,$(dirs_to_document))
diff --git a/api/system-current.txt b/api/system-current.txt
index d08039d..99779de 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -9479,7 +9479,7 @@
package android.view.accessibility {
public final class AccessibilityManager {
- method public int getAccessibilityWindowId(android.os.IBinder);
+ method public int getAccessibilityWindowId(@Nullable android.os.IBinder);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACCESSIBILITY) public void performAccessibilityShortcut();
}
diff --git a/cmds/incidentd/tests/ProtoFileReader_test.cpp b/cmds/incidentd/tests/ProtoFileReader_test.cpp
new file mode 100644
index 0000000..acb1bbb
--- /dev/null
+++ b/cmds/incidentd/tests/ProtoFileReader_test.cpp
@@ -0,0 +1,100 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#define DEBUG false
+#include "Log.h"
+
+#include <android-base/file.h>
+#include <android/util/ProtoFileReader.h>
+#include <android/util/ProtoOutputStream.h>
+#include <android/util/protobuf.h>
+#include <fcntl.h>
+#include <gtest/gtest.h>
+#include <signal.h>
+#include <string.h>
+
+#include "FdBuffer.h"
+#include "incidentd_util.h"
+
+using namespace android;
+using namespace android::base;
+using namespace android::os::incidentd;
+using ::testing::Test;
+
+const std::string kTestPath = GetExecutableDirectory();
+const std::string kTestDataPath = kTestPath + "/testdata/";
+
+status_t read(sp<ProtoFileReader> reader, size_t size) {
+ uint8_t const* buf;
+ while (size > 0 && (buf = reader->readBuffer()) != nullptr) {
+ size_t amt = reader->currentToRead();
+ if (size < amt) {
+ amt = size;
+ }
+ reader->move(amt);
+ size -= amt;
+ }
+
+ return NO_ERROR;
+}
+
+TEST(ProtoFileReaderTest, ParseOneLevel) {
+ const std::string testFile = kTestDataPath + "protoFile.txt";
+ size_t msg1Size = 10;
+ size_t msg2Size = 5 * 1024;
+ {
+ // Create a proto file
+ // TestProto {
+ // optional Section1 section1 = 1;
+ // optional Section2 section2 = 2;
+ // }
+
+ unique_fd fd(open(testFile.c_str(), O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR));
+ ASSERT_NE(fd.get(), -1);
+ ProtoOutputStream proto;
+ string field1;
+ field1.resize(msg1Size, 'h');
+ string field2;
+ field2.resize(msg2Size, 'a');
+ proto.write(FIELD_TYPE_MESSAGE | 1, field1.data(), field1.length());
+ proto.write(FIELD_TYPE_MESSAGE | 2, field2.data(), field2.length());
+ proto.flush(fd);
+ }
+
+ int fd = open(testFile.c_str(), O_RDONLY | O_CLOEXEC);
+ ASSERT_NE(fd, -1);
+
+ status_t err;
+ sp<ProtoFileReader> reader = new ProtoFileReader(fd);
+ int i = 0;
+ size_t msg_size[2];
+ while (reader->hasNext()) {
+ uint64_t fieldTag = reader->readRawVarint();
+ uint32_t fieldId = read_field_id(fieldTag);
+ uint8_t wireType = read_wire_type(fieldTag);
+ ASSERT_EQ(WIRE_TYPE_LENGTH_DELIMITED, wireType);
+ size_t sectionSize = reader->readRawVarint();
+ if (i < 2) {
+ msg_size[i] = sectionSize;
+ }
+ err = read(reader, sectionSize);
+ ASSERT_EQ(NO_ERROR, err);
+ i++;
+ }
+
+ ASSERT_EQ(2, i);
+
+ ASSERT_EQ(msg1Size, msg_size[0]);
+ ASSERT_EQ(msg2Size, msg_size[1]);
+ close(fd);
+}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 0d22f3a..c8bd275 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -127,6 +127,7 @@
import android.view.autofill.IAutofillWindowPresenter;
import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureManager;
+import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.Toolbar;
@@ -723,7 +724,7 @@
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback, WindowControllerCallback,
- AutofillManager.AutofillClient {
+ AutofillManager.AutofillClient, ContentCaptureManager.ContentCaptureClient {
private static final String TAG = "Activity";
private static final boolean DEBUG_LIFECYCLE = false;
@@ -1125,6 +1126,12 @@
return this;
}
+ /** @hide */
+ @Override
+ public final ContentCaptureClient getContentCaptureClient() {
+ return this;
+ }
+
/**
* Register an {@link Application.ActivityLifecycleCallbacks} instance that receives
* lifecycle callbacks for only this Activity.
@@ -6511,6 +6518,12 @@
return getComponentName();
}
+ /** @hide */
+ @Override
+ public final ComponentName contentCaptureClientGetComponentName() {
+ return getComponentName();
+ }
+
/**
* Retrieve a {@link SharedPreferences} object for accessing preferences
* that are private to this activity. This simply calls the underlying
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index b93aaa2..40cb29f 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -236,7 +236,7 @@
config.screenLayout = Configuration.reduceScreenLayout(sl,
config.screenHeightDp, config.screenWidthDp);
}
- config.smallestScreenWidthDp = config.screenWidthDp; // assume screen does not rotate
+ config.smallestScreenWidthDp = Math.min(config.screenWidthDp, config.screenHeightDp);
config.compatScreenWidthDp = config.screenWidthDp;
config.compatScreenHeightDp = config.screenHeightDp;
config.compatSmallestScreenWidthDp = config.smallestScreenWidthDp;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 98b658d..c48c878 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1143,7 +1143,7 @@
Context outerContext = ctx.getOuterContext();
ContentCaptureOptions options = outerContext.getContentCaptureOptions();
// Options is null when the service didn't whitelist the activity or package
- if (options != null) {
+ if (options != null && (options.lite || options.isWhitelisted(outerContext))) {
IBinder b = ServiceManager
.getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
IContentCaptureManager service = IContentCaptureManager.Stub.asInterface(b);
diff --git a/core/java/android/content/ContentCaptureOptions.java b/core/java/android/content/ContentCaptureOptions.java
index 76c4fb8..cb2142c 100644
--- a/core/java/android/content/ContentCaptureOptions.java
+++ b/core/java/android/content/ContentCaptureOptions.java
@@ -24,6 +24,9 @@
import android.util.ArraySet;
import android.util.Log;
import android.view.contentcapture.ContentCaptureManager;
+import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
+
+import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
@@ -78,12 +81,19 @@
*/
public final boolean lite;
+ /**
+ * Constructor for "lite" objects that are just used to enable a {@link ContentCaptureManager}
+ * for contexts belonging to the content capture service app.
+ */
public ContentCaptureOptions(int loggingLevel) {
this(/* lite= */ true, loggingLevel, /* maxBufferSize= */ 0,
/* idleFlushingFrequencyMs= */ 0, /* textChangeFlushingFrequencyMs= */ 0,
/* logHistorySize= */ 0, /* whitelistedComponents= */ null);
}
+ /**
+ * Default constructor.
+ */
public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
int textChangeFlushingFrequencyMs, int logHistorySize,
@Nullable ArraySet<ComponentName> whitelistedComponents) {
@@ -91,6 +101,16 @@
textChangeFlushingFrequencyMs, logHistorySize, whitelistedComponents);
}
+ /** @hide */
+ @VisibleForTesting
+ public ContentCaptureOptions(@Nullable ArraySet<ComponentName> whitelistedComponents) {
+ this(ContentCaptureManager.LOGGING_LEVEL_VERBOSE,
+ ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE,
+ ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS,
+ ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS,
+ ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE, whitelistedComponents);
+ }
+
private ContentCaptureOptions(boolean lite, int loggingLevel, int maxBufferSize,
int idleFlushingFrequencyMs, int textChangeFlushingFrequencyMs, int logHistorySize,
@Nullable ArraySet<ComponentName> whitelistedComponents) {
@@ -103,10 +123,6 @@
this.whitelistedComponents = whitelistedComponents;
}
- /**
- * @hide
- */
- @TestApi
public static ContentCaptureOptions forWhitelistingItself() {
final ActivityThread at = ActivityThread.currentActivityThread();
if (at == null) {
@@ -120,19 +136,27 @@
throw new SecurityException("Thou shall not pass!");
}
- final ContentCaptureOptions options = new ContentCaptureOptions(
- ContentCaptureManager.LOGGING_LEVEL_VERBOSE,
- ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE,
- ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS,
- ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS,
- ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE,
- /* whitelistedComponents= */ null);
+ final ContentCaptureOptions options =
+ new ContentCaptureOptions(/* whitelistedComponents= */ null);
// Always log, as it's used by test only
Log.i(TAG, "forWhitelistingItself(" + packageName + "): " + options);
return options;
}
+ /** @hide */
+ @VisibleForTesting
+ public boolean isWhitelisted(@NonNull Context context) {
+ if (whitelistedComponents == null) return true; // whole package is whitelisted
+ final ContentCaptureClient client = context.getContentCaptureClient();
+ if (client == null) {
+ // Shouldn't happen, but it doesn't hurt to check...
+ Log.w(TAG, "isWhitelisted(): no ContentCaptureClient on " + context);
+ return false;
+ }
+ return whitelistedComponents.contains(client.contentCaptureClientGetComponentName());
+ }
+
@Override
public String toString() {
if (lite) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index de04829..00238bf 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -70,6 +70,7 @@
import android.view.ViewDebug;
import android.view.WindowManager;
import android.view.autofill.AutofillManager.AutofillClient;
+import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
import android.view.textclassifier.TextClassificationManager;
import java.io.File;
@@ -5414,6 +5415,14 @@
/**
* @hide
*/
+ @Nullable
+ public ContentCaptureClient getContentCaptureClient() {
+ return null;
+ }
+
+ /**
+ * @hide
+ */
public final boolean isAutofillCompatibilityEnabled() {
final AutofillOptions options = getAutofillOptions();
return options != null && options.compatModeEnabled;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 83e15e8..abb68e7 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2030,9 +2030,10 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
- * {@link #hasSystemFeature(String, int)}: If this feature is supported, the Vulkan native API
- * will enumerate at least one {@code VkPhysicalDevice}, and the feature version will indicate
- * what level of optional hardware features limits it supports.
+ * {@link #hasSystemFeature(String, int)}: If this feature is supported, the Vulkan
+ * implementation on this device is hardware accelerated, and the Vulkan native API will
+ * enumerate at least one {@code VkPhysicalDevice}, and the feature version will indicate what
+ * level of optional hardware features limits it supports.
* <p>
* Level 0 includes the base Vulkan requirements as well as:
* <ul><li>{@code VkPhysicalDeviceFeatures::textureCompressionETC2}</li></ul>
@@ -2057,10 +2058,10 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
- * {@link #hasSystemFeature(String, int)}: If this feature is supported, the Vulkan native API
- * will enumerate at least one {@code VkPhysicalDevice}, and the feature version will indicate
- * what level of optional compute features that device supports beyond the Vulkan 1.0
- * requirements.
+ * {@link #hasSystemFeature(String, int)}: If this feature is supported, the Vulkan
+ * implementation on this device is hardware accelerated, and the Vulkan native API will
+ * enumerate at least one {@code VkPhysicalDevice}, and the feature version will indicate what
+ * level of optional compute features that device supports beyond the Vulkan 1.0 requirements.
* <p>
* Compute level 0 indicates:
* <ul>
@@ -2075,10 +2076,11 @@
/**
* Feature for {@link #getSystemAvailableFeatures} and
- * {@link #hasSystemFeature(String, int)}: The version of this feature indicates the highest
- * {@code VkPhysicalDeviceProperties::apiVersion} supported by the physical devices that support
- * the hardware level indicated by {@link #FEATURE_VULKAN_HARDWARE_LEVEL}. The feature version
- * uses the same encoding as Vulkan version numbers:
+ * {@link #hasSystemFeature(String, int)}: If this feature is supported, the Vulkan
+ * implementation on this device is hardware accelerated, and the feature version will indicate
+ * the highest {@code VkPhysicalDeviceProperties::apiVersion} supported by the physical devices
+ * that support the hardware level indicated by {@link #FEATURE_VULKAN_HARDWARE_LEVEL}. The
+ * feature version uses the same encoding as Vulkan version numbers:
* <ul>
* <li>Major version number in bits 31-22</li>
* <li>Minor version number in bits 21-12</li>
diff --git a/core/java/android/net/UrlQuerySanitizer.java b/core/java/android/net/UrlQuerySanitizer.java
index 5b67406..cf08b65 100644
--- a/core/java/android/net/UrlQuerySanitizer.java
+++ b/core/java/android/net/UrlQuerySanitizer.java
@@ -22,6 +22,8 @@
import java.util.Locale;
import java.util.Set;
import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
*
@@ -837,15 +839,11 @@
* @param string the escaped string
* @return the unescaped string.
*/
+ private static final Pattern plusOrPercent = Pattern.compile("[+%]");
public String unescape(String string) {
- // Early exit if no escaped characters.
- int firstEscape = string.indexOf('%');
- if ( firstEscape < 0) {
- firstEscape = string.indexOf('+');
- if (firstEscape < 0) {
- return string;
- }
- }
+ final Matcher matcher = plusOrPercent.matcher(string);
+ if (!matcher.find()) return string;
+ final int firstEscape = matcher.start();
int length = string.length();
@@ -855,8 +853,7 @@
char c = string.charAt(i);
if (c == '+') {
c = ' ';
- }
- else if ( c == '%' && i + 2 < length) {
+ } else if (c == '%' && i + 2 < length) {
char c1 = string.charAt(i + 1);
char c2 = string.charAt(i + 2);
if (isHexDigit(c1) && isHexDigit(c2)) {
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index f2aaead..e8b0d92 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -53,7 +53,6 @@
DEFAULT_FLAGS.put("settings_audio_switcher", "true");
DEFAULT_FLAGS.put("settings_mobile_network_v2", "true");
DEFAULT_FLAGS.put("settings_network_and_internet_v2", "true");
- DEFAULT_FLAGS.put("settings_slice_injection", "true");
DEFAULT_FLAGS.put("settings_systemui_theme", "true");
DEFAULT_FLAGS.put(DYNAMIC_SYSTEM, "false");
DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false");
diff --git a/core/java/android/util/SparseSetArray.java b/core/java/android/util/SparseSetArray.java
index 680e85f..c1873d7 100644
--- a/core/java/android/util/SparseSetArray.java
+++ b/core/java/android/util/SparseSetArray.java
@@ -44,6 +44,13 @@
}
/**
+ * Removes all mappings from this SparseSetArray.
+ */
+ public void clear() {
+ mData.clear();
+ }
+
+ /**
* @return whether a value exists at index n.
*/
public boolean contains(int n, T value) {
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index d12777f..882e6fd 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -1015,7 +1015,7 @@
* @hide
*/
@SystemApi
- public int getAccessibilityWindowId(IBinder windowToken) {
+ public int getAccessibilityWindowId(@Nullable IBinder windowToken) {
if (windowToken == null) {
return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index a977073..c2ad82f 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -294,6 +294,15 @@
private MainContentCaptureSession mMainSession;
/** @hide */
+ public interface ContentCaptureClient {
+ /**
+ * Gets the component name of the client.
+ */
+ @NonNull
+ ComponentName contentCaptureClientGetComponentName();
+ }
+
+ /** @hide */
public ContentCaptureManager(@NonNull Context context,
@NonNull IContentCaptureManager service, @NonNull ContentCaptureOptions options) {
mContext = Preconditions.checkNotNull(context, "context cannot be null");
diff --git a/core/java/com/android/internal/infra/GlobalWhitelistState.java b/core/java/com/android/internal/infra/GlobalWhitelistState.java
index dfa59b7..a0b2f94 100644
--- a/core/java/com/android/internal/infra/GlobalWhitelistState.java
+++ b/core/java/com/android/internal/infra/GlobalWhitelistState.java
@@ -35,11 +35,13 @@
*
* <p>This class is thread safe.
*/
+// TODO: add unit tests
public class GlobalWhitelistState {
// Uses full-name to avoid collision with service-provided mLock
protected final Object mGlobalWhitelistStateLock = new Object();
+ // TODO: should not be exposed directly
@Nullable
@GuardedBy("mGlobalWhitelistStateLock")
protected SparseArray<WhitelistHelper> mWhitelisterHelpers;
diff --git a/core/java/com/android/internal/infra/WhitelistHelper.java b/core/java/com/android/internal/infra/WhitelistHelper.java
index d7753db..9d653ba 100644
--- a/core/java/com/android/internal/infra/WhitelistHelper.java
+++ b/core/java/com/android/internal/infra/WhitelistHelper.java
@@ -98,9 +98,9 @@
@Nullable List<ComponentName> components) {
final ArraySet<String> packageNamesSet = packageNames == null ? null
: new ArraySet<>(packageNames);
- final ArraySet<ComponentName> componentssSet = components == null ? null
+ final ArraySet<ComponentName> componentsSet = components == null ? null
: new ArraySet<>(components);
- setWhitelist(packageNamesSet, componentssSet);
+ setWhitelist(packageNamesSet, componentsSet);
}
/**
@@ -170,7 +170,7 @@
pw.print("["); pw.print(components.valueAt(0));
for (int j = 1; j < components.size(); j++) {
- pw.print(", "); pw.print(components.valueAt(i));
+ pw.print(", "); pw.print(components.valueAt(j));
}
pw.println("]");
}
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index 6179918..dcf8d28 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -19,10 +19,10 @@
import static android.os.Process.*;
import android.annotation.UnsupportedAppUsage;
-import android.os.FileUtils;
import android.os.Process;
import android.os.StrictMode;
import android.os.SystemClock;
+import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.util.Slog;
@@ -247,6 +247,7 @@
pid = _pid;
if (parentPid < 0) {
final File procDir = new File("/proc", Integer.toString(pid));
+ uid = getUid(procDir.toString());
statFile = new File(procDir, "stat").toString();
cmdlineFile = new File(procDir, "cmdline").toString();
threadsDir = (new File(procDir, "task")).toString();
@@ -262,13 +263,22 @@
parentPid));
final File taskDir = new File(
new File(procDir, "task"), Integer.toString(pid));
+ uid = getUid(taskDir.toString());
statFile = new File(taskDir, "stat").toString();
cmdlineFile = null;
threadsDir = null;
threadStats = null;
workingThreads = null;
}
- uid = FileUtils.getUid(statFile.toString());
+ }
+
+ private static int getUid(String path) {
+ try {
+ return Os.stat(path).st_uid;
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to stat(" + path + "): " + e);
+ return -1;
+ }
}
}
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index ace88f5..c828cac 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2336,4 +2336,13 @@
// CATEGORY: SETTINGS
// OS: Q
ACTION_DISPLAY_WHITE_BALANCE_SETTING_CHANGED = 1703;
+
+ // OPEN: Settings > Pick SIM dialog
+ DIALOG_SIM_LIST = 1707;
+
+ // OPEN: Settings > Pick SIM (that supports calling) dialog
+ DIALOG_CALL_SIM_LIST = 1708;
+
+ // OPEN: Settings > Pick preferred SIM dialog
+ DIALOG_PREFERRED_SIM_PICKER = 1709;
}
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 1e0b0d8..dc2e6d5 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -478,6 +478,54 @@
}
repeated TrackedJob tracked_jobs = 4;
+ message ExecutionStats {
+ option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+ optional JobStatusDumpProto.Bucket standby_bucket = 1;
+
+ // The time after which this record should be considered invalid (out of date), in the
+ // elapsed realtime timebase.
+ optional int64 expiration_time_elapsed = 2;
+ optional int64 window_size_ms = 3;
+
+ /** The total amount of time the app ran in its respective bucket window size. */
+ optional int64 execution_time_in_window_ms = 4;
+ optional int32 bg_job_count_in_window = 5;
+
+ /**
+ * The total amount of time the app ran in the last
+ * {@link QuotaController#MAX_PERIOD_MS}.
+ */
+ optional int64 execution_time_in_max_period_ms = 6;
+ optional int32 bg_job_count_in_max_period = 7;
+
+ /**
+ * The time after which the sum of all the app's sessions plus
+ * ConstantsProto.QuotaController.in_quota_buffer_ms equals the quota. This is only
+ * valid if
+ * execution_time_in_window_ms >=
+ * ConstantsProto.QuotaController.allowed_time_per_period_ms
+ * or
+ * execution_time_in_max_period_ms >=
+ * ConstantsProto.QuotaController.max_execution_time_ms.
+ */
+ optional int64 quota_cutoff_time_elapsed = 8;
+
+ /**
+ * The time after which job_count_in_allowed_time should be considered invalid, in the
+ * elapsed realtime timebase.
+ */
+ optional int64 job_count_expiration_time_elapsed = 9;
+
+ /**
+ * The number of jobs that ran in at least the last
+ * ConstantsProto.QuotaController.allowed_time_per_period_ms.
+ * It may contain a few stale entries since cleanup won't happen exactly every
+ * ConstantsProto.QuotaController.allowed_time_per_period_ms.
+ */
+ optional int32 job_count_in_allowed_time = 10;
+ }
+
message Package {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -517,6 +565,8 @@
optional Timer timer = 2;
repeated TimingSession saved_sessions = 3;
+
+ repeated ExecutionStats execution_stats = 4;
}
repeated PackageStats package_stats = 5;
}
diff --git a/core/res/res/drawable/ic_content_copy_gm2.xml b/core/res/res/drawable/ic_content_copy_gm2.xml
index 940da94..ee58738 100644
--- a/core/res/res/drawable/ic_content_copy_gm2.xml
+++ b/core/res/res/drawable/ic_content_copy_gm2.xml
@@ -20,6 +20,6 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
- android:fillColor="#F999"
+ android:fillColor="?android:attr/textColorSecondary"
android:pathData="M18,21L4,21L4,7L2,7v14c0,1.1 0.9,2 2,2h14v-2zM21,17L21,3c0,-1.1 -0.9,-2 -2,-2L8,1c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h11c1.1,0 2,-0.9 2,-2zM19,17L8,17L8,3h11v14z"/>
</vector>
diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
index 138e24e3..4d5e262 100644
--- a/core/res/res/layout/chooser_grid.xml
+++ b/core/res/res/layout/chooser_grid.xml
@@ -28,6 +28,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alwaysShow="true"
+ android:elevation="1dp"
android:background="@drawable/bottomsheet_background">
<ImageView
@@ -66,6 +67,7 @@
android:listSelector="@color/transparent"
android:divider="@null"
android:scrollIndicators="top"
+ android:elevation="1dp"
android:nestedScrollingEnabled="true"/>
<TextView android:id="@+id/empty"
@@ -76,6 +78,7 @@
android:text="@string/noApplications"
android:padding="@dimen/chooser_edge_margin_normal"
android:gravity="center"
+ android:elevation="1dp"
android:visibility="gone"/>
</com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 03fb1fc..0ed9860 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -802,6 +802,8 @@
<item name="textAppearanceListItemSmall">@style/TextAppearance.DeviceDefault.ListItem</item>
<item name="textAppearanceListItemSecondary">@style/TextAppearance.DeviceDefault.ListItemSecondary</item>
+ <item name="backgroundDimAmount">0.7</item>
+
<!-- Button styles -->
<item name="buttonCornerRadius">@dimen/config_buttonCornerRadius</item>
<item name="buttonStyle">@style/Widget.DeviceDefault.Light.Button</item>
diff --git a/core/tests/coretests/src/android/content/ContentCaptureOptionsTest.java b/core/tests/coretests/src/android/content/ContentCaptureOptionsTest.java
new file mode 100644
index 0000000..c6f4fa2
--- /dev/null
+++ b/core/tests/coretests/src/android/content/ContentCaptureOptionsTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.ArraySet;
+import android.view.contentcapture.ContentCaptureManager.ContentCaptureClient;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+/**
+ * Unit test for {@link ContentCaptureOptions}.
+ *
+ * <p>To run it:
+ * {@code atest FrameworksCoreTests:android.content.ContentCaptureOptionsTest}
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class ContentCaptureOptionsTest {
+
+ private final ComponentName mContextComponent = new ComponentName("marco", "polo");
+ private final ComponentName mComp1 = new ComponentName("comp", "one");
+ private final ComponentName mComp2 = new ComponentName("two", "comp");
+
+ @Mock private Context mContext;
+ @Mock private ContentCaptureClient mClient;
+
+ @Before
+ public void setExpectation() {
+ when(mClient.contentCaptureClientGetComponentName()).thenReturn(mContextComponent);
+ when(mContext.getContentCaptureClient()).thenReturn(mClient);
+ }
+
+ @Test
+ public void testIsWhitelisted_nullWhitelistedComponents() {
+ ContentCaptureOptions options = new ContentCaptureOptions(null);
+ assertThat(options.isWhitelisted(mContext)).isTrue();
+ }
+
+ @Test
+ public void testIsWhitelisted_emptyWhitelistedComponents() {
+ ContentCaptureOptions options = new ContentCaptureOptions(toSet((ComponentName) null));
+ assertThat(options.isWhitelisted(mContext)).isFalse();
+ }
+
+ @Test
+ public void testIsWhitelisted_notWhitelisted() {
+ ContentCaptureOptions options = new ContentCaptureOptions(toSet(mComp1, mComp2));
+ assertThat(options.isWhitelisted(mContext)).isFalse();
+ }
+
+ @Test
+ public void testIsWhitelisted_whitelisted() {
+ ContentCaptureOptions options = new ContentCaptureOptions(toSet(mComp1, mContextComponent));
+ assertThat(options.isWhitelisted(mContext)).isTrue();
+ }
+
+ @Test
+ public void testIsWhitelisted_invalidContext() {
+ ContentCaptureOptions options = new ContentCaptureOptions(toSet(mContextComponent));
+ Context invalidContext = mock(Context.class); // has no client
+ assertThat(options.isWhitelisted(invalidContext)).isFalse();
+ }
+
+ @Test
+ public void testIsWhitelisted_clientWithNullComponentName() {
+ ContentCaptureOptions options = new ContentCaptureOptions(toSet(mContextComponent));
+ ContentCaptureClient client = mock(ContentCaptureClient.class);
+ Context context = mock(Context.class);
+ when(context.getContentCaptureClient()).thenReturn(client);
+
+ assertThat(options.isWhitelisted(context)).isFalse();
+ }
+
+ @NonNull
+ private ArraySet<ComponentName> toSet(@Nullable ComponentName... comps) {
+ ArraySet<ComponentName> set = new ArraySet<>();
+ if (comps != null) {
+ for (int i = 0; i < comps.length; i++) {
+ set.add(comps[i]);
+ }
+ }
+ return set;
+ }
+}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index e4a93e7..dbbe1b4 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -41,6 +41,7 @@
<permission name="android.permission.MODIFY_PHONE_STATE"/>
<permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
<permission name="android.permission.RECEIVE_EMERGENCY_BROADCAST"/>
+ <permission name="android.permission.START_ACTIVITIES_FROM_BACKGROUND"/>
</privapp-permissions>
<privapp-permissions package="com.android.defcontainer">
diff --git a/libs/hwui/DeviceInfo.cpp b/libs/hwui/DeviceInfo.cpp
index cf5d7ce..0a9d965 100644
--- a/libs/hwui/DeviceInfo.cpp
+++ b/libs/hwui/DeviceInfo.cpp
@@ -45,12 +45,12 @@
1920, // viewportH
};
-const DeviceInfo* DeviceInfo::get() {
+DeviceInfo* DeviceInfo::get() {
static DeviceInfo sDeviceInfo;
return &sDeviceInfo;
}
-DisplayInfo QueryDisplayInfo() {
+static DisplayInfo QueryDisplayInfo() {
if (Properties::isolatedProcess) {
return sDummyDisplay;
}
@@ -65,6 +65,27 @@
return displayInfo;
}
+static float QueryMaxRefreshRate() {
+ if (Properties::isolatedProcess) {
+ return sDummyDisplay.fps;
+ }
+
+ const sp<IBinder> token = SurfaceComposerClient::getInternalDisplayToken();
+ LOG_ALWAYS_FATAL_IF(token == nullptr,
+ "Failed to get display info because internal display is disconnected");
+
+ Vector<DisplayInfo> configs;
+ configs.reserve(10);
+ status_t status = SurfaceComposerClient::getDisplayConfigs(token, &configs);
+ LOG_ALWAYS_FATAL_IF(status, "Failed to getDisplayConfigs, error %d", status);
+ LOG_ALWAYS_FATAL_IF(configs.size() == 0, "getDisplayConfigs returned 0 configs?");
+ float max = 0.0f;
+ for (auto& info : configs) {
+ max = std::max(max, info.fps);
+ }
+ return max;
+}
+
static void queryWideColorGamutPreference(sk_sp<SkColorSpace>* colorSpace, SkColorType* colorType) {
if (Properties::isolatedProcess) {
*colorSpace = SkColorSpace::MakeSRGB();
@@ -103,7 +124,7 @@
}
}
-DeviceInfo::DeviceInfo() {
+DeviceInfo::DeviceInfo() : mMaxRefreshRate(QueryMaxRefreshRate()) {
#if HWUI_NULL_GPU
mMaxTextureSize = NULL_GPU_MAX_TEXTURE_SIZE;
#else
@@ -119,7 +140,11 @@
}
void DeviceInfo::setMaxTextureSize(int maxTextureSize) {
- const_cast<DeviceInfo*>(DeviceInfo::get())->mMaxTextureSize = maxTextureSize;
+ DeviceInfo::get()->mMaxTextureSize = maxTextureSize;
+}
+
+void DeviceInfo::onDisplayConfigChanged() {
+ mDisplayInfo = QueryDisplayInfo();
}
} /* namespace uirenderer */
diff --git a/libs/hwui/DeviceInfo.h b/libs/hwui/DeviceInfo.h
index 2bab5d3..0e3f119 100644
--- a/libs/hwui/DeviceInfo.h
+++ b/libs/hwui/DeviceInfo.h
@@ -32,7 +32,7 @@
PREVENT_COPY_AND_ASSIGN(DeviceInfo);
public:
- static const DeviceInfo* get();
+ static DeviceInfo* get();
// this value is only valid after the GPU has been initialized and there is a valid graphics
// context or if you are using the HWUI_NULL_GPU
@@ -40,6 +40,9 @@
const DisplayInfo& displayInfo() const { return mDisplayInfo; }
sk_sp<SkColorSpace> getWideColorSpace() const { return mWideColorSpace; }
SkColorType getWideColorType() const { return mWideColorType; }
+ float getMaxRefreshRate() const { return mMaxRefreshRate; }
+
+ void onDisplayConfigChanged();
private:
friend class renderthread::RenderThread;
@@ -51,6 +54,7 @@
DisplayInfo mDisplayInfo;
sk_sp<SkColorSpace> mWideColorSpace;
SkColorType mWideColorType;
+ const float mMaxRefreshRate;
};
} /* namespace uirenderer */
diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp
index 9998854..19f509c 100644
--- a/libs/hwui/Properties.cpp
+++ b/libs/hwui/Properties.cpp
@@ -67,7 +67,7 @@
bool Properties::isolatedProcess = false;
int Properties::contextPriority = 0;
-uint32_t Properties::defaultRenderAhead = 0;
+int Properties::defaultRenderAhead = -1;
static int property_get_int(const char* key, int defaultValue) {
char buf[PROPERTY_VALUE_MAX] = {
@@ -130,9 +130,8 @@
enableForceDarkSupport = property_get_bool(PROPERTY_ENABLE_FORCE_DARK, true);
- defaultRenderAhead =
- std::max(0u, std::min(2u, static_cast<uint32_t>(property_get_int(
- PROPERTY_RENDERAHEAD, render_ahead().value_or(0)))));
+ defaultRenderAhead = std::max(-1, std::min(2, property_get_int(PROPERTY_RENDERAHEAD,
+ render_ahead().value_or(0))));
return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw);
}
diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h
index 3105e58..3e91c63 100644
--- a/libs/hwui/Properties.h
+++ b/libs/hwui/Properties.h
@@ -253,7 +253,7 @@
ANDROID_API static int contextPriority;
- static uint32_t defaultRenderAhead;
+ static int defaultRenderAhead;
private:
static ProfileType sProfileType;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 2957b14..f326ce8 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -105,13 +105,13 @@
, mGenerationID(0)
, mOpaque(!translucent)
, mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord()))
- , mJankTracker(&thread.globalProfileData(), thread.mainDisplayInfo())
+ , mJankTracker(&thread.globalProfileData(), DeviceInfo::get()->displayInfo())
, mProfiler(mJankTracker.frames(), thread.timeLord().frameIntervalNanos())
, mContentDrawBounds(0, 0, 0, 0)
, mRenderPipeline(std::move(renderPipeline)) {
rootRenderNode->makeRoot();
mRenderNodes.emplace_back(rootRenderNode);
- mProfiler.setDensity(mRenderThread.mainDisplayInfo().density);
+ mProfiler.setDensity(DeviceInfo::get()->displayInfo().density);
setRenderAheadDepth(Properties::defaultRenderAhead);
}
@@ -153,16 +153,23 @@
mNativeSurface = nullptr;
}
+ if (mRenderAheadDepth == 0 && DeviceInfo::get()->getMaxRefreshRate() > 66.6f) {
+ mFixedRenderAhead = false;
+ mRenderAheadCapacity = 1;
+ } else {
+ mFixedRenderAhead = true;
+ mRenderAheadCapacity = mRenderAheadDepth;
+ }
+
ColorMode colorMode = mWideColorGamut ? ColorMode::WideColorGamut : ColorMode::SRGB;
bool hasSurface = mRenderPipeline->setSurface(mNativeSurface.get(), mSwapBehavior, colorMode,
- mRenderAheadDepth);
+ mRenderAheadCapacity);
mFrameNumber = -1;
if (hasSurface) {
mHaveNewSurface = true;
mSwapHistory.clear();
- applyRenderAheadSettings();
} else {
mRenderThread.removeFrameCallback(this);
mGenerationID++;
@@ -403,6 +410,23 @@
mRenderThread.pushBackFrameCallback(this);
}
+void CanvasContext::setPresentTime() {
+ int64_t presentTime = NATIVE_WINDOW_TIMESTAMP_AUTO;
+ int renderAhead = 0;
+ const auto frameIntervalNanos = mRenderThread.timeLord().frameIntervalNanos();
+ if (mFixedRenderAhead) {
+ renderAhead = std::min(mRenderAheadDepth, mRenderAheadCapacity);
+ } else if (frameIntervalNanos < 15_ms) {
+ renderAhead = std::min(1, static_cast<int>(mRenderAheadCapacity));
+ }
+
+ if (renderAhead) {
+ presentTime = mCurrentFrameInfo->get(FrameInfoIndex::Vsync) +
+ (frameIntervalNanos * (renderAhead + 1));
+ }
+ native_window_set_buffers_timestamp(mNativeSurface.get(), presentTime);
+}
+
void CanvasContext::draw() {
SkRect dirty;
mDamageAccumulator.finish(&dirty);
@@ -415,14 +439,9 @@
mCurrentFrameInfo->markIssueDrawCommandsStart();
Frame frame = mRenderPipeline->getFrame();
+ setPresentTime();
SkRect windowDirty = computeDirtyRect(frame, &dirty);
- if (mRenderAheadDepth) {
- auto presentTime =
- mCurrentFrameInfo->get(FrameInfoIndex::Vsync) +
- (mRenderThread.timeLord().frameIntervalNanos() * (mRenderAheadDepth + 1));
- native_window_set_buffers_timestamp(mNativeSurface.get(), presentTime);
- }
bool drew = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry, &mLayerUpdateQueue,
mContentDrawBounds, mOpaque, mLightInfo, mRenderNodes,
@@ -656,18 +675,12 @@
return width == mLastFrameWidth && height == mLastFrameHeight;
}
-void CanvasContext::applyRenderAheadSettings() {
- if (mNativeSurface && !mRenderAheadDepth) {
- native_window_set_buffers_timestamp(mNativeSurface.get(), NATIVE_WINDOW_TIMESTAMP_AUTO);
- }
-}
-
-void CanvasContext::setRenderAheadDepth(uint32_t renderAhead) {
- if (renderAhead > 2 || renderAhead == mRenderAheadDepth || mNativeSurface) {
+void CanvasContext::setRenderAheadDepth(int renderAhead) {
+ if (renderAhead > 2 || renderAhead < 0 || mNativeSurface) {
return;
}
- mRenderAheadDepth = renderAhead;
- applyRenderAheadSettings();
+ mFixedRenderAhead = true;
+ mRenderAheadDepth = static_cast<uint32_t>(renderAhead);
}
SkRect CanvasContext::computeDirtyRect(const Frame& frame, SkRect* dirty) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 912b125..f9de002 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -204,7 +204,7 @@
}
// Must be called before setSurface
- void setRenderAheadDepth(uint32_t renderAhead);
+ void setRenderAheadDepth(int renderAhead);
SkISize getNextFrameSize() const;
@@ -221,7 +221,7 @@
bool isSwapChainStuffed();
bool surfaceRequiresRedraw();
- void applyRenderAheadSettings();
+ void setPresentTime();
SkRect computeDirtyRect(const Frame& frame, SkRect* dirty);
@@ -240,7 +240,9 @@
// painted onto its surface.
bool mIsDirty = false;
SwapBehavior mSwapBehavior = SwapBehavior::kSwap_default;
+ bool mFixedRenderAhead = false;
uint32_t mRenderAheadDepth = 0;
+ uint32_t mRenderAheadCapacity = 0;
struct SwapHistory {
SkRect damage;
nsecs_t vsyncTime;
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index eca7d88..41cb8fd 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -60,8 +60,10 @@
class DisplayEventReceiverWrapper : public VsyncSource {
public:
- DisplayEventReceiverWrapper(std::unique_ptr<DisplayEventReceiver>&& receiver)
- : mDisplayEventReceiver(std::move(receiver)) {}
+ DisplayEventReceiverWrapper(std::unique_ptr<DisplayEventReceiver>&& receiver,
+ const std::function<void()>& onDisplayConfigChanged)
+ : mDisplayEventReceiver(std::move(receiver))
+ , mOnDisplayConfigChanged(onDisplayConfigChanged) {}
virtual void requestNextVsync() override {
status_t status = mDisplayEventReceiver->requestNextVsync();
@@ -79,6 +81,9 @@
case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
latest = ev.header.timestamp;
break;
+ case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
+ mOnDisplayConfigChanged();
+ break;
}
}
}
@@ -90,6 +95,7 @@
private:
std::unique_ptr<DisplayEventReceiver> mDisplayEventReceiver;
+ std::function<void()> mOnDisplayConfigChanged;
};
class DummyVsyncSource : public VsyncSource {
@@ -160,22 +166,29 @@
// Register the FD
mLooper->addFd(receiver->getFd(), 0, Looper::EVENT_INPUT,
RenderThread::displayEventReceiverCallback, this);
- mVsyncSource = new DisplayEventReceiverWrapper(std::move(receiver));
+ mVsyncSource = new DisplayEventReceiverWrapper(std::move(receiver), [this] {
+ DeviceInfo::get()->onDisplayConfigChanged();
+ setupFrameInterval();
+ });
} else {
mVsyncSource = new DummyVsyncSource(this);
}
}
void RenderThread::initThreadLocals() {
- mDisplayInfo = DeviceInfo::get()->displayInfo();
- nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / mDisplayInfo.fps);
- mTimeLord.setFrameInterval(frameIntervalNanos);
- mDispatchFrameDelay = static_cast<nsecs_t>(frameIntervalNanos * .25f);
+ setupFrameInterval();
initializeDisplayEventReceiver();
mEglManager = new EglManager();
mRenderState = new RenderState(*this);
mVkManager = new VulkanManager();
- mCacheManager = new CacheManager(mDisplayInfo);
+ mCacheManager = new CacheManager(DeviceInfo::get()->displayInfo());
+}
+
+void RenderThread::setupFrameInterval() {
+ auto& displayInfo = DeviceInfo::get()->displayInfo();
+ nsecs_t frameIntervalNanos = static_cast<nsecs_t>(1000000000 / displayInfo.fps);
+ mTimeLord.setFrameInterval(frameIntervalNanos);
+ mDispatchFrameDelay = static_cast<nsecs_t>(frameIntervalNanos * .25f);
}
void RenderThread::requireGlContext() {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 6bb26fd..c96e284 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -102,8 +102,6 @@
ProfileDataContainer& globalProfileData() { return mGlobalProfileData; }
Readback& readback();
- const DisplayInfo& mainDisplayInfo() { return mDisplayInfo; }
-
GrContext* getGrContext() const { return mGrContext.get(); }
void setGrContext(sk_sp<GrContext> cxt);
@@ -149,13 +147,12 @@
void initThreadLocals();
void initializeDisplayEventReceiver();
+ void setupFrameInterval();
static int displayEventReceiverCallback(int fd, int events, void* data);
void drainDisplayEventQueue();
void dispatchFrameCallbacks();
void requestVsync();
- DisplayInfo mDisplayInfo;
-
VsyncSource* mVsyncSource;
bool mVsyncRequested;
std::set<IFrameCallback*> mFrameCallbacks;
diff --git a/libs/hwui/tests/unit/CacheManagerTests.cpp b/libs/hwui/tests/unit/CacheManagerTests.cpp
index 210fced..3f1ef93 100644
--- a/libs/hwui/tests/unit/CacheManagerTests.cpp
+++ b/libs/hwui/tests/unit/CacheManagerTests.cpp
@@ -33,7 +33,7 @@
}
RENDERTHREAD_SKIA_PIPELINE_TEST(CacheManager, trimMemory) {
- DisplayInfo displayInfo = renderThread.mainDisplayInfo();
+ DisplayInfo displayInfo = DeviceInfo::get()->displayInfo();
GrContext* grContext = renderThread.getGrContext();
ASSERT_TRUE(grContext != nullptr);
diff --git a/libs/protoutil/src/ProtoFileReader.cpp b/libs/protoutil/src/ProtoFileReader.cpp
index 4017979..bbb1fe3 100644
--- a/libs/protoutil/src/ProtoFileReader.cpp
+++ b/libs/protoutil/src/ProtoFileReader.cpp
@@ -127,7 +127,8 @@
if (!ensure_data()) {
return;
}
- const size_t chunk = mMaxOffset - mOffset < amt ? amt : mMaxOffset - mOffset;
+ const size_t chunk =
+ mMaxOffset - mOffset > amt ? amt : mMaxOffset - mOffset;
mOffset += chunk;
amt -= chunk;
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index a7f8933..ae99126 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -472,7 +472,10 @@
}
boolean isTracking = mIsTracking;
Rect rect = mNotificationList.getClipBounds();
- float clippedHeight = rect.bottom;
+ float clippedHeight = 0;
+ if (rect != null) {
+ clippedHeight = rect.bottom;
+ }
if (!handled && event.getActionMasked() == MotionEvent.ACTION_UP
&& mIsSwipingVerticallyToClose) {
if (mSettleClosePercentage < mPercentageFromBottom && isTracking) {
diff --git a/packages/NetworkStack/res/values/config.xml b/packages/NetworkStack/res/values/config.xml
index 90f96e0..704788d 100644
--- a/packages/NetworkStack/res/values/config.xml
+++ b/packages/NetworkStack/res/values/config.xml
@@ -35,4 +35,8 @@
</string-array>
<string-array name="config_captive_portal_fallback_probe_specs" translatable="false">
</string-array>
-</resources>
\ No newline at end of file
+
+ <!-- Customized default DNS Servers address. -->
+ <string-array name="config_default_dns_servers" translatable="false">
+ </string-array>
+</resources>
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
index af0e3bb..ca6c17a 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpClient.java
@@ -45,6 +45,7 @@
import android.content.Context;
import android.net.DhcpResults;
+import android.net.InetAddresses;
import android.net.TrafficStats;
import android.net.ip.IpClient;
import android.net.metrics.DhcpClientEvent;
@@ -67,6 +68,7 @@
import com.android.internal.util.StateMachine;
import com.android.internal.util.TrafficStatsConstants;
import com.android.internal.util.WakeupMessage;
+import com.android.networkstack.R;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -500,6 +502,18 @@
private void acceptDhcpResults(DhcpResults results, String msg) {
mDhcpLease = results;
+ if (mDhcpLease.dnsServers.isEmpty()) {
+ // supplement customized dns servers
+ String[] dnsServersList =
+ mContext.getResources().getStringArray(R.array.config_default_dns_servers);
+ for (final String dnsServer : dnsServersList) {
+ try {
+ mDhcpLease.dnsServers.add(InetAddresses.parseNumericAddress(dnsServer));
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Invalid default DNS server: " + dnsServer, e);
+ }
+ }
+ }
mOffer = null;
Log.d(TAG, msg + " lease: " + mDhcpLease);
notifySuccess();
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
index d21b5f7..b8ab94c 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpServer.java
@@ -647,4 +647,9 @@
}
}
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
}
diff --git a/packages/NetworkStack/src/android/net/ip/IpClient.java b/packages/NetworkStack/src/android/net/ip/IpClient.java
index 80d139c..96e09fa 100644
--- a/packages/NetworkStack/src/android/net/ip/IpClient.java
+++ b/packages/NetworkStack/src/android/net/ip/IpClient.java
@@ -557,6 +557,11 @@
checkNetworkStackCallingPermission();
IpClient.this.removeKeepalivePacketFilter(slot);
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
}
public String getInterfaceName() {
diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
index a0a90fd..a6d7484 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
@@ -251,6 +251,11 @@
}
}
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
}
private static class NetworkMonitorImpl extends INetworkMonitor.Stub {
@@ -325,5 +330,10 @@
checkNetworkStackCallingPermission();
mNm.notifyNetworkCapabilitiesChanged(nc);
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
}
}
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java
index bee4bbd9..6a6bf83 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreService.java
@@ -494,4 +494,9 @@
listener.onComplete(makeStatus(ERROR_INTERNAL_INTERRUPTED));
return true;
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
}
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/RegularMaintenanceJobService.java b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/RegularMaintenanceJobService.java
index 2775fde..bea7052 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/RegularMaintenanceJobService.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/ipmemorystore/RegularMaintenanceJobService.java
@@ -91,6 +91,11 @@
}
@Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
+
+ @Override
public IBinder asBinder() {
return null;
}
diff --git a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java b/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java
index 7d5e9e3..f0e2f1b 100644
--- a/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java
+++ b/packages/NetworkStack/tests/src/android/net/dhcp/DhcpServerTest.java
@@ -133,6 +133,11 @@
public void onStatusAvailable(int statusCode) {
assertEquals(STATUS_SUCCESS, statusCode);
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
};
@Before
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
index a00eff7..87346e5 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/ipmemorystore/IpMemoryStoreServiceTest.java
@@ -136,6 +136,11 @@
public IBinder asBinder() {
return null;
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
};
}
@@ -156,6 +161,11 @@
public IBinder asBinder() {
return null;
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
};
}
@@ -178,6 +188,11 @@
public IBinder asBinder() {
return null;
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
};
}
@@ -200,6 +215,11 @@
public IBinder asBinder() {
return null;
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
};
}
@@ -219,6 +239,11 @@
public IBinder asBinder() {
return null;
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
};
}
diff --git a/packages/SettingsLib/res/layout/preference_checkable_two_target.xml b/packages/SettingsLib/res/layout/preference_checkable_two_target.xml
index 1a47afc..f532caa 100644
--- a/packages/SettingsLib/res/layout/preference_checkable_two_target.xml
+++ b/packages/SettingsLib/res/layout/preference_checkable_two_target.xml
@@ -42,6 +42,7 @@
android:layout_height="wrap_content"
android:gravity="start|center_vertical"
android:minWidth="56dp"
+ android:minHeight="48dp"
android:orientation="horizontal"
android:clipToPadding="false"
android:paddingTop="4dp"
diff --git a/packages/SystemUI/docs/clock-plugins.md b/packages/SystemUI/docs/clock-plugins.md
new file mode 100644
index 0000000..5e4f6c7
--- /dev/null
+++ b/packages/SystemUI/docs/clock-plugins.md
@@ -0,0 +1,92 @@
+# Clock Plugins
+
+## Introduction
+
+The clock appearing on the lock screen and always on display (AOD) can be
+customized via the ClockPlugin plugin interface.
+
+## System Health
+
+Clocks are high risk for battery consumption and screen burn-in because they
+modify the UI of AOD.
+
+To reduce battery consumption, it is recommended to
+target a maximum on-pixel-ratio (OPR) of 5%. Clocks that are composed of
+large blocks of color that cause the OPR to exceed 5% should be avoided.
+
+To prevent screen burn-in, clocks should not be composed of large solid
+blocks of color, and the clock should be moved around the screen to
+distribute the on pixels across a large number of pixels. Software
+burn-in testing is a good starting point to assess the pixel shifting
+(clock movement) scheme and shape of the clock.
+
+### Software Burn-In Test
+
+The goal is to look for bright spots in the luminosity average over a period of
+time. It is difficult to define a threshold where burn-in will occur. It is,
+therefore, recommended to compare against an element on AOD that is known not
+to cause problems.
+
+For clock face that contain color, it is recommended to use an all white
+version of the face. Since white has the highest luminosity, this version of
+the clock face represents the worst case scenario.
+
+To start, generate a sequence of screenshots for each minute over a 12 hr interval.
+
+```
+serial = '84TY004MS' # serial number for the device
+count = 1
+t = datetime.datetime(2019, 1, 1)
+stop = t + datetime.timedelta(hours=12)
+if not os.path.exists(OUTPUT_FOLDER):
+ raise RuntimeError('output folder "%s" does not exist' % OUTPUT_FOLDER)
+while t <= stop:
+ os.system("adb -s %s shell 'date %s ; am broadcast -a android.intent.action.TIME_SET'" % (serial, t.strftime('%m%d%H%M%Y.%S')))
+ os.system('adb -s %s shell screencap -p > %s/screencap_%06d.png' % (serial, OUTPUT_FOLDER, count))
+ t += datetime.timedelta(minutes=1)
+ count += 1
+```
+
+Average the luminosity of the screenshots.
+
+```
+#!python
+import numpy
+import scipy.ndimage
+from imageio import imread, imwrite
+import matplotlib.pylab as plt
+import os
+import os.path
+
+def images(path):
+ return [os.path.join(path, name) for name in os.listdir(path) if name.endswith('.png')]
+
+def average(images):
+ AVG = None
+ for name in images:
+ IM = scipy.ndimage.imread(name, mode='L')
+ A = numpy.array(IM, dtype=numpy.double)
+ if AVG is None:
+ AVG = A
+ else:
+ AVG += A
+ AVG /= len(images)
+ return numpy.array(AVG, dtype=numpy.uint8)
+
+def main(path):
+ ims = images(path)
+ if len(ims) == 0:
+ raise ValueError("folder '%s' doesn't contain any png files" % path)
+ AVG = average(ims)
+ imwrite('average.png', AVG)
+ plt.imshow(AVG)
+ plt.show()
+
+if __name__=='__main__':
+ import sys
+ main(sys.argv[1])
+```
+
+Look for bright spots in the luminosity average. If bright spots are found,
+action should be taken to change the shape of the clock face or increase the
+amount of pixel shifting.
diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/analog_thumbnail.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/analog_thumbnail.png
index 83d714b..4a0972f 100644
--- a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/analog_thumbnail.png
+++ b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/analog_thumbnail.png
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/bubble_thumbnail.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/bubble_thumbnail.png
index 8d0e6ed..a7d5a0d 100644
--- a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/bubble_thumbnail.png
+++ b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/bubble_thumbnail.png
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/default_thumbnail.png b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/default_thumbnail.png
index 1ac0113..812dc9d 100644
--- a/packages/SystemUI/res-keyguard/drawable-xxxhdpi/default_thumbnail.png
+++ b/packages/SystemUI/res-keyguard/drawable-xxxhdpi/default_thumbnail.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/quick_settings_header_info.xml b/packages/SystemUI/res/layout/quick_settings_header_info.xml
index 37c6d9f..5a33f82 100644
--- a/packages/SystemUI/res/layout/quick_settings_header_info.xml
+++ b/packages/SystemUI/res/layout/quick_settings_header_info.xml
@@ -22,17 +22,6 @@
android:paddingStart="@dimen/status_bar_padding_start"
android:paddingEnd="@dimen/status_bar_padding_end">
- <TextView
- android:id="@+id/long_press_tooltip"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="start|center_vertical"
- android:alpha="0"
- android:text="@string/quick_settings_header_onboarding_text"
- android:textAppearance="@style/TextAppearance.QS.TileLabel"
- android:textColor="?android:attr/textColorSecondary"
- android:visibility="invisible" />
-
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
@@ -45,8 +34,7 @@
android:layout_height="match_parent"
android:layout_gravity="start|center_vertical"
android:layout_weight="1"
- android:gravity="center_vertical"
- android:alpha="0" >
+ android:gravity="center_vertical" >
<LinearLayout
android:id = "@+id/alarm_container"
diff --git a/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java b/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java
index 922c65e..b3fc69e 100644
--- a/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java
@@ -59,7 +59,10 @@
} else if (SliceBroadcastRelay.ACTION_UNREGISTER.equals(intent.getAction())) {
Uri uri = intent.getParcelableExtra(SliceBroadcastRelay.EXTRA_URI);
if (DEBUG) Log.d(TAG, "Unregister " + uri);
- getAndRemoveRelay(uri).unregister(mContext);
+ BroadcastRelay relay = getAndRemoveRelay(uri);
+ if (relay != null) {
+ relay.unregister(mContext);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java b/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java
index f19445c..a1a7566 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java
@@ -132,15 +132,18 @@
}
@Override
+ protected void onFinishInflate() {
+ setSelected(true);
+ }
+
+ @Override
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
// Only show marquee when visible
if (visibility == VISIBLE) {
setEllipsize(TextUtils.TruncateAt.MARQUEE);
- setSelected(true);
} else {
setEllipsize(TextUtils.TruncateAt.END);
- setSelected(false);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 2e3065a..346ffa2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -18,8 +18,6 @@
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.annotation.ColorInt;
import android.app.ActivityManager;
import android.app.AlarmManager;
@@ -39,7 +37,6 @@
import android.service.notification.ZenModeConfig;
import android.text.format.DateUtils;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.Pair;
import android.util.StatsLog;
import android.view.DisplayCutout;
@@ -56,7 +53,6 @@
import com.android.settingslib.Utils;
import com.android.systemui.BatteryMeterView;
-import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.DarkIconDispatcher;
@@ -123,10 +119,6 @@
private View mSystemIconsView;
private View mQuickQsStatusIcons;
private View mHeaderTextContainerView;
- /** View containing the next alarm and ringer mode info. */
- private View mStatusContainer;
- /** Tooltip for educating users that they can long press on icons to see more details. */
- private View mLongPressTooltipView;
private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
private AlarmManager.AlarmClockInfo mNextAlarm;
@@ -146,8 +138,6 @@
private BatteryMeterView mBatteryRemainingIcon;
private PrivacyItemController mPrivacyItemController;
- /** Counts how many times the long press tooltip has been shown to the user. */
- private int mShownCount;
private final BroadcastReceiver mRingerReceiver = new BroadcastReceiver() {
@Override
@@ -159,11 +149,6 @@
private boolean mHasTopCutout = false;
private boolean mPrivacyChipLogged = false;
- /**
- * Runnable for automatically fading out the long press tooltip (as if it were animating away).
- */
- private final Runnable mAutoFadeOutTooltipRunnable = () -> hideLongPressTooltip(false);
-
private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() {
@Override
public void privacyChanged(List<PrivacyItem> privacyItems) {
@@ -183,7 +168,6 @@
mStatusBarIconController = statusBarIconController;
mActivityStarter = activityStarter;
mPrivacyItemController = privacyItemController;
- mShownCount = getStoredShownCount();
}
@Override
@@ -199,10 +183,8 @@
iconContainer.setShouldRestrictIcons(false);
mIconManager = new TintedIconManager(iconContainer);
- // Views corresponding to the header info section (e.g. tooltip and next alarm).
+ // Views corresponding to the header info section (e.g. ringer and next alarm).
mHeaderTextContainerView = findViewById(R.id.header_text_container);
- mLongPressTooltipView = findViewById(R.id.long_press_tooltip);
- mStatusContainer = findViewById(R.id.status_container);
mStatusSeparator = findViewById(R.id.status_separator);
mNextAlarmIcon = findViewById(R.id.next_alarm_icon);
mNextAlarmTextView = findViewById(R.id.next_alarm_text);
@@ -267,7 +249,6 @@
boolean ringerVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
mStatusSeparator.setVisibility(alarmVisible && ringerVisible ? View.VISIBLE
: View.GONE);
- updateTooltipShow();
}
}
@@ -351,8 +332,6 @@
mClockView.useWallpaperTextColor(shouldUseWallpaperTextColor);
}
-
-
@Override
public void onRtlPropertiesChanged(int layoutDirection) {
super.onRtlPropertiesChanged(layoutDirection);
@@ -457,21 +436,6 @@
mPrivacyChip.setExpanded(expansionFraction > 0.5);
mPrivacyChipAlphaAnimator.setPosition(keyguardExpansionFraction);
}
-
- // Check the original expansion fraction - we don't want to show the tooltip until the
- // panel is pulled all the way out.
- if (expansionFraction == 1f) {
- // QS is fully expanded, bring in the tooltip.
- showLongPressTooltip();
- }
- }
-
- /** Returns the latest stored tooltip shown count from SharedPreferences. */
- private int getStoredShownCount() {
- return Prefs.getInt(
- mContext,
- Prefs.Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT,
- TOOLTIP_NOT_YET_SHOWN_COUNT);
}
public void disable(int state1, int state2, boolean animate) {
@@ -592,109 +556,6 @@
updateStatusText();
}
- private void updateTooltipShow() {
- if (hasStatusText()) {
- hideLongPressTooltip(true /* shouldShowStatusText */);
- } else {
- hideStatusText();
- }
- updateHeaderTextContainerAlphaAnimator();
- }
-
- private boolean hasStatusText() {
- return mNextAlarmTextView.getVisibility() == View.VISIBLE
- || mRingerModeTextView.getVisibility() == View.VISIBLE;
- }
-
- /**
- * Animates in the long press tooltip (as long as the next alarm text isn't currently occupying
- * the space).
- */
- public void showLongPressTooltip() {
- // If we have status text to show, don't bother fading in the tooltip.
- if (hasStatusText()) {
- return;
- }
-
- if (mShownCount < MAX_TOOLTIP_SHOWN_COUNT) {
- mLongPressTooltipView.animate().cancel();
- mLongPressTooltipView.setVisibility(View.VISIBLE);
- mLongPressTooltipView.animate()
- .alpha(1f)
- .setDuration(FADE_ANIMATION_DURATION_MS)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mHandler.postDelayed(
- mAutoFadeOutTooltipRunnable, AUTO_FADE_OUT_DELAY_MS);
- }
- })
- .start();
-
- // Increment and drop the shown count in prefs for the next time we're deciding to
- // fade in the tooltip. We first sanity check that the tooltip count hasn't changed yet
- // in prefs (say, from a long press).
- if (getStoredShownCount() <= mShownCount) {
- Prefs.putInt(mContext, Prefs.Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT, ++mShownCount);
- }
- }
- }
-
- /**
- * Fades out the long press tooltip if it's partially visible - short circuits any running
- * animation. Additionally has the ability to fade in the status info text.
- *
- * @param shouldShowStatusText whether we should fade in the status text
- */
- private void hideLongPressTooltip(boolean shouldShowStatusText) {
- mLongPressTooltipView.animate().cancel();
- if (mLongPressTooltipView.getVisibility() == View.VISIBLE
- && mLongPressTooltipView.getAlpha() != 0f) {
- mHandler.removeCallbacks(mAutoFadeOutTooltipRunnable);
- mLongPressTooltipView.animate()
- .alpha(0f)
- .setDuration(FADE_ANIMATION_DURATION_MS)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (DEBUG) Log.d(TAG, "hideLongPressTooltip: Hid long press tip");
- mLongPressTooltipView.setVisibility(View.INVISIBLE);
-
- if (shouldShowStatusText) {
- showStatus();
- }
- }
- })
- .start();
- } else {
- mLongPressTooltipView.setVisibility(View.INVISIBLE);
- if (shouldShowStatusText) {
- showStatus();
- }
- }
- }
-
- /**
- * Fades in the updated status text. Note that if there's already a status showing, this will
- * immediately fade it out and fade in the updated status.
- */
- private void showStatus() {
- mStatusContainer.setAlpha(0f);
-
- mStatusContainer.animate()
- .alpha(1f)
- .setDuration(FADE_ANIMATION_DURATION_MS)
- .start();
- }
-
- /** Fades out the status text. */
- private void hideStatusText() {
- mStatusContainer.animate()
- .alpha(0f)
- .setDuration(FADE_ANIMATION_DURATION_MS)
- .start();
- }
-
public void updateEverything() {
post(() -> setClickable(!mExpanded));
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 6101593..ebafb81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -693,6 +693,9 @@
@Override
public void onKeyguardBouncerChanged(boolean bouncer) {
+ if (mLockIcon == null) {
+ return;
+ }
mLockIcon.setBouncerVisible(bouncer);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 058cb2d..ebda585 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -1193,6 +1193,20 @@
}
}
+ /**
+ * Returns best effort count of visible notifications.
+ */
+ public int getVisibleNotificationCount() {
+ int count = 0;
+ for (int i = 0; i < getChildCount(); i++) {
+ final View child = getChildAt(i);
+ if (child.getVisibility() != View.GONE && child instanceof ExpandableNotificationRow) {
+ count++;
+ }
+ }
+ return count;
+ }
+
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
private boolean isCurrentlyAnimating() {
return mStateAnimator.isRunning();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 0171d7f..26e0a70 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -59,6 +59,16 @@
private int mClockPreferredY;
/**
+ * Whether or not there is a custom clock face on keyguard.
+ */
+ private boolean mHasCustomClock;
+
+ /**
+ * Whether or not the NSSL contains any visible notifications.
+ */
+ private boolean mHasVisibleNotifs;
+
+ /**
* Height of notification stack: Sum of height of each notification.
*/
private int mNotificationStackHeight;
@@ -117,7 +127,7 @@
public void setup(int minTopMargin, int maxShadeBottom, int notificationStackHeight,
float panelExpansion, int parentHeight, int keyguardStatusHeight, int clockPreferredY,
- float dark, float emptyDragAmount) {
+ boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float emptyDragAmount) {
mMinTopMargin = minTopMargin + mContainerTopPadding;
mMaxShadeBottom = maxShadeBottom;
mNotificationStackHeight = notificationStackHeight;
@@ -125,6 +135,8 @@
mHeight = parentHeight;
mKeyguardStatusHeight = keyguardStatusHeight;
mClockPreferredY = clockPreferredY;
+ mHasCustomClock = hasCustomClock;
+ mHasVisibleNotifs = hasVisibleNotifs;
mDarkAmount = dark;
mEmptyDragAmount = emptyDragAmount;
}
@@ -179,6 +191,9 @@
clockYDark = MathUtils.max(0, clockYDark);
float clockYRegular = getExpandedClockPosition();
+ if (mHasCustomClock && !mHasVisibleNotifs) {
+ clockYRegular = clockYDark;
+ }
float clockYBouncer = -mKeyguardStatusHeight;
// Move clock up while collapsing the shade
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 2207e04..c39a494 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -637,6 +637,8 @@
totalHeight,
mKeyguardStatusView.getHeight(),
clockPreferredY,
+ hasCustomClock(),
+ mNotificationStackScroller.getVisibleNotificationCount() != 0,
mInterpolatedDarkAmount,
mEmptyDragAmount);
mClockPositionAlgorithm.run(mClockPositionResult);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java
index c6e85c3..19e1a5c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java
@@ -95,6 +95,22 @@
}
@Test
+ public void testUnregisterWithoutRegister() {
+ Uri testUri = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority("something")
+ .path("test")
+ .build();
+ SliceBroadcastRelayHandler relayHandler = new SliceBroadcastRelayHandler();
+ relayHandler.mContext = spy(mContext);
+
+ Intent intent = new Intent(SliceBroadcastRelay.ACTION_UNREGISTER);
+ intent.putExtra(SliceBroadcastRelay.EXTRA_URI, ContentProvider.maybeAddUserId(testUri, 0));
+ relayHandler.handleIntent(intent);
+ // No crash
+ }
+
+ @Test
public void testRelay() {
Receiver.sReceiver = mock(BroadcastReceiver.class);
Uri testUri = new Uri.Builder()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index 9354648..f191cab 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -41,6 +41,8 @@
private static final float ZERO_DRAG = 0.f;
private static final float OPAQUE = 1.f;
private static final float TRANSPARENT = 0.f;
+ private static final boolean HAS_CUSTOM_CLOCK = false;
+ private static final boolean HAS_VISIBLE_NOTIFS = false;
private KeyguardClockPositionAlgorithm mClockPositionAlgorithm;
private KeyguardClockPositionAlgorithm.Result mClockPosition;
@@ -48,11 +50,18 @@
private float mPanelExpansion;
private int mKeyguardStatusHeight;
private float mDark;
+ private int mPreferredClockY;
+ private boolean mHasCustomClock;
+ private boolean mHasVisibleNotifs;
@Before
public void setUp() {
mClockPositionAlgorithm = new KeyguardClockPositionAlgorithm();
mClockPosition = new KeyguardClockPositionAlgorithm.Result();
+
+ mPreferredClockY = PREFERRED_CLOCK_Y;
+ mHasCustomClock = HAS_CUSTOM_CLOCK;
+ mHasVisibleNotifs = HAS_VISIBLE_NOTIFS;
}
@Test
@@ -293,6 +302,71 @@
assertThat(mClockPosition.stackScrollerPadding).isEqualTo(0);
}
+ @Test
+ public void preferredCustomClockPositionNoNotifications() {
+ // GIVEN on the lock screen with a custom clock and no visible notifications
+ givenLockScreen();
+ mPreferredClockY = 100;
+ mHasCustomClock = true;
+ mHasVisibleNotifs = false;
+ // AND given empty height for clock and stack scroller
+ mNotificationStackHeight = EMPTY_HEIGHT;
+ mKeyguardStatusHeight = EMPTY_HEIGHT;
+ // WHEN the clock position algorithm is run
+ positionClock();
+ // THEN the clock Y position is the preferred Y position.
+ assertThat(mClockPosition.clockY).isEqualTo(100);
+ }
+
+ @Test
+ public void preferredDefaultClockPositionNoNotifications() {
+ // GIVEN on the lock screen with a custom clock and no visible notifications
+ givenLockScreen();
+ mPreferredClockY = 100;
+ mHasCustomClock = false;
+ mHasVisibleNotifs = false;
+ // AND given empty height for clock and stack scroller
+ mNotificationStackHeight = EMPTY_HEIGHT;
+ mKeyguardStatusHeight = EMPTY_HEIGHT;
+ // WHEN the clock position algorithm is run
+ positionClock();
+ // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2) and not
+ // preferred.
+ assertThat(mClockPosition.clockY).isEqualTo(1000);
+ }
+
+ @Test
+ public void preferredCustomClockPositionWithVisibleNotifications() {
+ // GIVEN on the lock screen with a custom clock and visible notifications
+ givenLockScreen();
+ mPreferredClockY = 100;
+ mHasCustomClock = true;
+ mHasVisibleNotifs = true;
+ // AND given empty height for clock and stack scroller
+ mNotificationStackHeight = EMPTY_HEIGHT;
+ mKeyguardStatusHeight = EMPTY_HEIGHT;
+ // WHEN the clock position algorithm is run
+ positionClock();
+ // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2).
+ assertThat(mClockPosition.clockY).isEqualTo(1000);
+ }
+
+ @Test
+ public void preferredCustomClockPositionWithVisibleNotificationsOnAod() {
+ // GIVEN on the lock screen with a custom clock and visible notifications
+ givenAOD();
+ mPreferredClockY = 100;
+ mHasCustomClock = true;
+ mHasVisibleNotifs = true;
+ // AND given empty height for clock and stack scroller
+ mNotificationStackHeight = EMPTY_HEIGHT;
+ mKeyguardStatusHeight = EMPTY_HEIGHT;
+ // WHEN the clock position algorithm is run
+ positionClock();
+ // THEN the clock Y position is the preferred Y position.
+ assertThat(mClockPosition.clockY).isEqualTo(100);
+ }
+
private void givenAOD() {
mPanelExpansion = 1.f;
mDark = 1.f;
@@ -305,8 +379,8 @@
private void positionClock() {
mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight,
- mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, PREFERRED_CLOCK_Y, mDark,
- ZERO_DRAG);
+ mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, mPreferredClockY,
+ mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG);
mClockPositionAlgorithm.run(mClockPosition);
}
}
diff --git a/packages/overlays/AccentColorCinnamonOverlay/res/values/colors_device_defaults.xml b/packages/overlays/AccentColorCinnamonOverlay/res/values/colors_device_defaults.xml
index c420ab6..a99f705 100644
--- a/packages/overlays/AccentColorCinnamonOverlay/res/values/colors_device_defaults.xml
+++ b/packages/overlays/AccentColorCinnamonOverlay/res/values/colors_device_defaults.xml
@@ -18,5 +18,5 @@
-->
<resources>
<color name="accent_device_default_light">#AF6050</color>
- <color name="accent_device_default_dark">#9D6962</color>
+ <color name="accent_device_default_dark">#C3A6A2</color>
</resources>
diff --git a/packages/overlays/AccentColorOceanOverlay/res/values/colors_device_defaults.xml b/packages/overlays/AccentColorOceanOverlay/res/values/colors_device_defaults.xml
index 6aec805..449639b 100644
--- a/packages/overlays/AccentColorOceanOverlay/res/values/colors_device_defaults.xml
+++ b/packages/overlays/AccentColorOceanOverlay/res/values/colors_device_defaults.xml
@@ -18,5 +18,5 @@
-->
<resources>
<color name="accent_device_default_light">#0C80A7</color>
- <color name="accent_device_default_dark">#347D98</color>
+ <color name="accent_device_default_dark">#28BDD7</color>
</resources>
diff --git a/packages/overlays/AccentColorOrchidOverlay/res/values/colors_device_defaults.xml b/packages/overlays/AccentColorOrchidOverlay/res/values/colors_device_defaults.xml
index 049f8b8..47079a8 100644
--- a/packages/overlays/AccentColorOrchidOverlay/res/values/colors_device_defaults.xml
+++ b/packages/overlays/AccentColorOrchidOverlay/res/values/colors_device_defaults.xml
@@ -18,5 +18,5 @@
-->
<resources>
<color name="accent_device_default_light">#C42CC9</color>
- <color name="accent_device_default_dark">#C42CC9</color>
+ <color name="accent_device_default_dark">#E68AED</color>
</resources>
diff --git a/packages/overlays/AccentColorSpaceOverlay/res/values/colors_device_defaults.xml b/packages/overlays/AccentColorSpaceOverlay/res/values/colors_device_defaults.xml
index b6f757c..f147aeb 100644
--- a/packages/overlays/AccentColorSpaceOverlay/res/values/colors_device_defaults.xml
+++ b/packages/overlays/AccentColorSpaceOverlay/res/values/colors_device_defaults.xml
@@ -18,5 +18,5 @@
-->
<resources>
<color name="accent_device_default_light">#47618A</color>
- <color name="accent_device_default_dark">#5D7A92</color>
+ <color name="accent_device_default_dark">#99ACCC</color>
</resources>
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 3babb6d..bf76fdb 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -7182,6 +7182,21 @@
// OS: Q
QS_UI_MODE_NIGHT = 1706;
+ // OPEN: Settings > Pick SIM dialog
+ // CATEGORY: SETTINGS
+ // OS: Q
+ DIALOG_SIM_LIST = 1707;
+
+ // OPEN: Settings > Pick SIM (that supports calling) dialog
+ // CATEGORY: SETTINGS
+ // OS: Q
+ DIALOG_CALL_SIM_LIST = 1708;
+
+ // OPEN: Settings > Pick preferred SIM dialog
+ // CATEGORY: SETTINGS
+ // OS: Q
+ DIALOG_PREFERRED_SIM_PICKER = 1709;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 834987c..ea044cf 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -2098,6 +2098,9 @@
// Firmware alert code. Only valid when the stats was triggered by a firmware
// alert, otherwise -1.
optional int32 firmware_alert_code = 4 [default = -1];
+
+ // Absolute milliseconds from device boot when these stats were sampled
+ optional int64 time_stamp_ms = 5;
}
message DeviceMobilityStatePnoScanStats {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 6e2c228..334262f 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -2504,7 +2504,7 @@
* registered.
*/
@Override
- public int getAccessibilityWindowId(IBinder windowToken) {
+ public int getAccessibilityWindowId(@Nullable IBinder windowToken) {
synchronized (mLock) {
if (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID) {
throw new SecurityException("Only SYSTEM can call getAccessibilityWindowId");
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 7f411d8..a2d3d4c 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -781,36 +781,46 @@
@GuardedBy("mGlobalWhitelistStateLock")
public ContentCaptureOptions getOptions(@UserIdInt int userId,
@NonNull String packageName) {
+ boolean packageWhitelisted;
+ ArraySet<ComponentName> whitelistedComponents = null;
synchronized (mGlobalWhitelistStateLock) {
- if (!isWhitelisted(userId, packageName)) {
- if (packageName.equals(mServicePackages.get(userId))) {
+ packageWhitelisted = isWhitelisted(userId, packageName);
+ if (!packageWhitelisted) {
+ // Full package is not whitelisted: check individual components first
+ whitelistedComponents = getWhitelistedComponents(userId, packageName);
+ if (whitelistedComponents == null
+ && packageName.equals(mServicePackages.get(userId))) {
+ // No components whitelisted either, but let it go because it's the
+ // service's own package
if (verbose) Slog.v(mTag, "getOptionsForPackage() lite for " + packageName);
return new ContentCaptureOptions(mDevCfgLoggingLevel);
}
- if (verbose) {
- Slog.v(mTag, "getOptionsForPackage(" + packageName + "): not whitelisted");
- }
+ }
+ } // synchronized
+
+ // Restrict what temporary services can whitelist
+ if (Build.IS_USER && mServiceNameResolver.isTemporary(userId)) {
+ if (!packageName.equals(mServicePackages.get(userId))) {
+ Slog.w(mTag, "Ignoring package " + packageName + " while using temporary "
+ + "service " + mServicePackages.get(userId));
return null;
}
-
- final ArraySet<ComponentName> whitelistedComponents =
- getWhitelistedComponents(userId, packageName);
- if (Build.IS_USER && mServiceNameResolver.isTemporary(userId)) {
- if (!packageName.equals(mServicePackages.get(userId))) {
- Slog.w(mTag, "Ignoring package " + packageName
- + " while using temporary service " + mServicePackages.get(userId));
- return null;
- }
- }
- final ContentCaptureOptions options = new ContentCaptureOptions(mDevCfgLoggingLevel,
- mDevCfgMaxBufferSize, mDevCfgIdleFlushingFrequencyMs,
- mDevCfgTextChangeFlushingFrequencyMs, mDevCfgLogHistorySize,
- whitelistedComponents);
- if (verbose) {
- Slog.v(mTag, "getOptionsForPackage(" + packageName + "): " + options);
- }
- return options;
}
+
+ if (!packageWhitelisted && whitelistedComponents == null) {
+ // No can do!
+ if (verbose) {
+ Slog.v(mTag, "getOptionsForPackage(" + packageName + "): not whitelisted");
+ }
+ return null;
+ }
+
+ final ContentCaptureOptions options = new ContentCaptureOptions(mDevCfgLoggingLevel,
+ mDevCfgMaxBufferSize, mDevCfgIdleFlushingFrequencyMs,
+ mDevCfgTextChangeFlushingFrequencyMs, mDevCfgLogHistorySize,
+ whitelistedComponents);
+ if (verbose) Slog.v(mTag, "getOptionsForPackage(" + packageName + "): " + options);
+ return options;
}
@Override
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 5a42e78..a7921b5 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -35,13 +35,11 @@
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.content.ComponentName;
-import android.content.ContentCaptureOptions;
import android.content.pm.ActivityPresentationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ServiceInfo;
import android.os.Binder;
-import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.UserHandle;
@@ -60,7 +58,6 @@
import android.view.contentcapture.DataRemovalRequest;
import com.android.internal.annotations.GuardedBy;
-import com.android.internal.infra.WhitelistHelper;
import com.android.internal.os.IResultReceiver;
import com.android.server.LocalServices;
import com.android.server.contentcapture.RemoteContentCaptureService.ContentCaptureServiceCallbacks;
@@ -97,12 +94,6 @@
new ContentCaptureServiceRemoteCallback();
/**
- * List of packages that are whitelisted to be content captured.
- */
- @GuardedBy("mLock")
- private final WhitelistHelper mWhitelistHelper = new WhitelistHelper();
-
- /**
* List of conditions keyed by package.
*/
@GuardedBy("mLock")
@@ -131,6 +122,7 @@
* Updates the reference to the remote service.
*/
private void updateRemoteServiceLocked(boolean disabled) {
+ if (mMaster.verbose) Slog.v(TAG, "updateRemoteService(disabled=" + disabled + ")");
if (mRemoteService != null) {
if (mMaster.debug) Slog.d(TAG, "updateRemoteService(): destroying old remote service");
mRemoteService.destroy();
@@ -247,7 +239,8 @@
final int displayId = activityPresentationInfo.displayId;
final ComponentName componentName = activityPresentationInfo.componentName;
final boolean whiteListed = mMaster.mGlobalContentCaptureOptions.isWhitelisted(mUserId,
- componentName);
+ componentName) || mMaster.mGlobalContentCaptureOptions.isWhitelisted(mUserId,
+ componentName.getPackageName());
final ComponentName serviceComponentName = getServiceComponentName();
final boolean enabled = isEnabledLocked();
if (mMaster.mRequestsHistory != null) {
@@ -462,40 +455,6 @@
@GuardedBy("mLock")
@Nullable
- ContentCaptureOptions getOptionsForPackageLocked(@NonNull String packageName) {
- if (!mWhitelistHelper.isWhitelisted(packageName)) {
- if (packageName.equals(getServicePackageName())) {
- if (mMaster.verbose) Slog.v(mTag, "getOptionsForPackage() lite for " + packageName);
- return new ContentCaptureOptions(mMaster.mDevCfgLoggingLevel);
- }
- if (mMaster.verbose) {
- Slog.v(mTag, "getOptionsForPackage(" + packageName + "): not whitelisted");
- }
- return null;
- }
-
- final ArraySet<ComponentName> whitelistedComponents = mWhitelistHelper
- .getWhitelistedComponents(packageName);
- if (Build.IS_USER && isTemporaryServiceSetLocked()) {
- final String servicePackageName = getServicePackageName();
- if (!packageName.equals(servicePackageName)) {
- Slog.w(mTag, "Ignoring package " + packageName
- + " while using temporary service " + servicePackageName);
- return null;
- }
- }
- final ContentCaptureOptions options = new ContentCaptureOptions(mMaster.mDevCfgLoggingLevel,
- mMaster.mDevCfgMaxBufferSize, mMaster.mDevCfgIdleFlushingFrequencyMs,
- mMaster.mDevCfgTextChangeFlushingFrequencyMs, mMaster.mDevCfgLogHistorySize,
- whitelistedComponents);
- if (mMaster.verbose) {
- Slog.v(mTag, "getOptionsForPackage(" + packageName + "): " + options);
- }
- return options;
- }
-
- @GuardedBy("mLock")
- @Nullable
ArraySet<ContentCaptureCondition> getContentCaptureConditionsLocked(
@NonNull String packageName) {
return mConditionsByPkg.get(packageName);
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 1bd367c..1fa62ce 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -3152,7 +3152,7 @@
void removeLocked(final int uid) {
if (uid == Process.SYSTEM_UID) {
- Slog.wtf(TAG, "removeLocked: Shouldn't for UID=" + uid);
+ // If a force-stop occurs for a system-uid package, ignore it.
return;
}
boolean didRemove = false;
@@ -3247,7 +3247,7 @@
// Only called for ephemeral apps
void removeForStoppedLocked(final int uid) {
if (uid == Process.SYSTEM_UID) {
- Slog.wtf(TAG, "removeForStoppedLocked: Shouldn't for UID=" + uid);
+ // If a force-stop occurs for a system-uid package, ignore it.
return;
}
boolean didRemove = false;
@@ -3291,7 +3291,7 @@
void removeUserLocked(int userHandle) {
if (userHandle == UserHandle.USER_SYSTEM) {
- Slog.wtf(TAG, "removeForStoppedLocked: Shouldn't for user=" + userHandle);
+ // If we're told we're removing the system user, ignore it.
return;
}
boolean didRemove = false;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 6c3a169..ee8bb05 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -735,19 +735,18 @@
}
}
- final DetailedState state = DetailedState.DISCONNECTED;
-
if (wasFirstNetwork || wasDefault) {
- maybeLogBroadcast(nai, state, type, wasDefault);
- mService.sendLegacyNetworkBroadcast(nai, state, type);
+ maybeLogBroadcast(nai, DetailedState.DISCONNECTED, type, wasDefault);
+ mService.sendLegacyNetworkBroadcast(nai, DetailedState.DISCONNECTED, type);
}
if (!list.isEmpty() && wasFirstNetwork) {
if (DBG) log("Other network available for type " + type +
", sending connected broadcast");
final NetworkAgentInfo replacement = list.get(0);
- maybeLogBroadcast(replacement, state, type, mService.isDefaultNetwork(replacement));
- mService.sendLegacyNetworkBroadcast(replacement, state, type);
+ maybeLogBroadcast(replacement, DetailedState.CONNECTED, type,
+ mService.isDefaultNetwork(replacement));
+ mService.sendLegacyNetworkBroadcast(replacement, DetailedState.CONNECTED, type);
}
}
@@ -2812,6 +2811,11 @@
EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE,
mNai.network.netId));
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
}
private boolean networkRequiresValidation(NetworkAgentInfo nai) {
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index cc3b43a..c2b35c18 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -96,6 +96,7 @@
"media.extractor", // system/bin/mediaextractor
"media.metrics", // system/bin/mediametrics
"media.codec", // vendor/bin/hw/android.hardware.media.omx@1.0-service
+ "media.swcodec", // /apex/com.android.media.swcodec/bin/mediaswcodec
"com.android.bluetooth", // Bluetooth service
"/system/bin/statsd", // Stats daemon
};
@@ -108,6 +109,7 @@
"android.hardware.graphics.allocator@2.0::IAllocator",
"android.hardware.graphics.composer@2.1::IComposer",
"android.hardware.health@2.0::IHealth",
+ "android.hardware.media.c2@1.0::IComponentStore",
"android.hardware.media.omx@1.0::IOmx",
"android.hardware.media.omx@1.0::IOmxStore",
"android.hardware.sensors@1.0::ISensors",
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 0271354..24f8fc2 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -3830,8 +3830,11 @@
void serviceTimeout(ProcessRecord proc) {
String anrMessage = null;
-
synchronized(mAm) {
+ if (proc.isDebugging()) {
+ // The app's being debugged, ignore timeout.
+ return;
+ }
if (proc.executingServices.size() == 0 || proc.thread == null) {
return;
}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 49930c1..e891e6e 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1557,7 +1557,7 @@
mService.mBatteryStatsService.noteProcessAnr(processName, uid);
}
- if (isSilentAnr()) {
+ if (isSilentAnr() && !isDebugging()) {
kill("bg anr", true);
return;
}
diff --git a/services/core/java/com/android/server/am/TEST_MAPPING b/services/core/java/com/android/server/am/TEST_MAPPING
index f198464..d56cb79 100644
--- a/services/core/java/com/android/server/am/TEST_MAPPING
+++ b/services/core/java/com/android/server/am/TEST_MAPPING
@@ -46,26 +46,12 @@
],
"postsubmit": [
{
- "name": "CtsActivityManagerDeviceTestCases"
- },
- {
- "name": "CtsActivityManagerDeviceSdk25TestCases"
- },
- {
"name": "FrameworksServicesTests",
"options": [
{
"include-filter": "com.android.server.am."
}
]
- },
- {
- "name": "WmTests",
- "options": [
- {
- "include-filter": "com.android.server.am."
- }
- ]
}
]
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 4ce6d91..05be100 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -771,7 +771,7 @@
case MSG_L_SCOCLIENT_DIED:
synchronized (mSetModeLock) {
synchronized (mDeviceStateLock) {
- mBtHelper.scoClientDied(msg.arg1);
+ mBtHelper.scoClientDied(msg.obj);
}
}
break;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index b6879a3..d3af8f07 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -519,6 +519,10 @@
AudioSystem.DEVICE_OUT_AUX_LINE;
// Devices for which the volume is always max, no volume panel
int mFullVolumeDevices = 0;
+ // Devices for the which use the "absolute volume" concept (framework sends audio signal
+ // full scale, and volume control separately) and can be used for multiple use cases reflected
+ // by the audio mode (e.g. media playback in MODE_NORMAL, and phone calls in MODE_IN_CALL).
+ int mAbsVolumeMultiModeCaseDevices = AudioSystem.DEVICE_OUT_HEARING_AID;
private final boolean mMonitorRotation;
@@ -2050,6 +2054,49 @@
}
}
+ /**
+ * Manage an audio mode change for audio devices that use an "absolute volume" model,
+ * i.e. the framework sends the full scale signal, and the actual volume for the use case
+ * is communicated separately.
+ */
+ void updateAbsVolumeMultiModeDevices(int oldMode, int newMode) {
+ if (oldMode == newMode) {
+ return;
+ }
+ int streamType = AudioSystem.STREAM_MUSIC;
+ switch (newMode) {
+ case AudioSystem.MODE_IN_COMMUNICATION:
+ case AudioSystem.MODE_IN_CALL:
+ streamType = AudioSystem.STREAM_VOICE_CALL;
+ break;
+ case AudioSystem.MODE_NORMAL:
+ streamType = AudioSystem.STREAM_MUSIC;
+ break;
+ case AudioSystem.MODE_RINGTONE:
+ // not changing anything for ringtone
+ return;
+ case AudioSystem.MODE_CURRENT:
+ case AudioSystem.MODE_INVALID:
+ default:
+ // don't know what to do in this case, better bail
+ return;
+ }
+ final int device = AudioSystem.getDevicesForStream(streamType);
+ if ((device & mAbsVolumeMultiModeCaseDevices) == 0) {
+ return;
+ }
+
+ // handling of specific interfaces goes here:
+ if ((device & mAbsVolumeMultiModeCaseDevices) == AudioSystem.DEVICE_OUT_HEARING_AID) {
+ final int index = getStreamVolume(streamType);
+ mModeLogger.log(new AudioEventLogger.StringEvent("setMode to "
+ + AudioSystem.modeToString(newMode)
+ + " causes setting HEARING_AID volume to idx:" + index
+ + " stream:" + AudioSystem.streamToString(streamType)));
+ mDeviceBroker.postSetHearingAidVolumeIndex(index * 10, streamType);
+ }
+ }
+
private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
String caller, int uid) {
if (DEBUG_VOL) {
@@ -3039,9 +3086,9 @@
}
}
- // must be called synchronized on mSetModeLock
// setModeInt() returns a valid PID if the audio mode was successfully set to
// any mode other than NORMAL.
+ @GuardedBy("mDeviceBroker.mSetModeLock")
private int setModeInt(int mode, IBinder cb, int pid, String caller) {
if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ", caller="
+ caller + ")"); }
@@ -3063,6 +3110,7 @@
break;
}
}
+ final int oldMode = mMode;
int status = AudioSystem.AUDIO_STATUS_OK;
int actualMode;
do {
@@ -3134,6 +3182,9 @@
setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true, caller);
updateStreamVolumeAlias(true /*updateVolumes*/, caller);
+
+ // change of mode may require volume to be re-applied on some devices
+ updateAbsVolumeMultiModeDevices(oldMode, actualMode);
}
return newModeOwnerPid;
}
diff --git a/services/core/java/com/android/server/job/controllers/QuotaController.java b/services/core/java/com/android/server/job/controllers/QuotaController.java
index 1820acf..ccd1db4 100644
--- a/services/core/java/com/android/server/job/controllers/QuotaController.java
+++ b/services/core/java/com/android/server/job/controllers/QuotaController.java
@@ -29,6 +29,7 @@
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
+import android.app.AppGlobals;
import android.app.IUidObserver;
import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
@@ -49,6 +50,7 @@
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.util.SparseSetArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
@@ -277,9 +279,9 @@
.append(", ")
.append("bgJobCountInMaxPeriod=").append(bgJobCountInMaxPeriod).append(", ")
.append("quotaCutoffTime=").append(quotaCutoffTimeElapsed).append(", ")
- .append("jobCountExpirationTime").append(jobCountExpirationTimeElapsed)
+ .append("jobCountExpirationTime=").append(jobCountExpirationTimeElapsed)
.append(", ")
- .append("jobCountInAllowedTime").append(jobCountInAllowedTime)
+ .append("jobCountInAllowedTime=").append(jobCountInAllowedTime)
.toString();
}
@@ -338,6 +340,9 @@
/** List of UIDs currently in the foreground. */
private final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
+ /** Cached mapping of UIDs (for all users) to a list of packages in the UID. */
+ private final SparseSetArray<String> mUidToPackageCache = new SparseSetArray<>();
+
/**
* List of jobs that started while the UID was in the TOP state. There will be no more than
* 16 ({@link JobSchedulerService#MAX_JOB_CONTEXTS_COUNT}) running at once, so an ArraySet is
@@ -421,6 +426,22 @@
}
};
+ private final BroadcastReceiver mPackageAddedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent == null) {
+ return;
+ }
+ if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+ return;
+ }
+ final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+ synchronized (mLock) {
+ mUidToPackageCache.remove(uid);
+ }
+ }
+ };
+
/**
* The rolling window size for each standby bucket. Within each window, an app will have 10
* minutes to run its jobs.
@@ -469,6 +490,9 @@
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+ final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+ mContext.registerReceiverAsUser(mPackageAddedReceiver, UserHandle.ALL, filter, null, null);
+
// Set up the app standby bucketing tracker
UsageStatsManagerInternal usageStats = LocalServices.getService(
UsageStatsManagerInternal.class);
@@ -502,10 +526,15 @@
@Override
public void prepareForExecutionLocked(JobStatus jobStatus) {
- if (DEBUG) Slog.d(TAG, "Prepping for " + jobStatus.toShortString());
+ if (DEBUG) {
+ Slog.d(TAG, "Prepping for " + jobStatus.toShortString());
+ }
final int uid = jobStatus.getSourceUid();
if (mActivityManagerInternal.getUidProcessState(uid) <= ActivityManager.PROCESS_STATE_TOP) {
+ if (DEBUG) {
+ Slog.d(TAG, jobStatus.toShortString() + " is top started job");
+ }
mTopStartedJobs.add(jobStatus);
// Top jobs won't count towards quota so there's no need to involve the Timer.
return;
@@ -518,7 +547,7 @@
timer = new Timer(uid, userId, packageName);
mPkgTimers.add(userId, packageName, timer);
}
- timer.startTrackingJob(jobStatus);
+ timer.startTrackingJobLocked(jobStatus);
}
@Override
@@ -645,7 +674,7 @@
if (timer != null) {
if (timer.isActive()) {
Slog.wtf(TAG, "onAppRemovedLocked called before Timer turned off.");
- timer.dropEverything();
+ timer.dropEverythingLocked();
}
mPkgTimers.delete(userId, packageName);
}
@@ -657,6 +686,7 @@
}
mExecutionStatsCache.delete(userId, packageName);
mForegroundUids.delete(uid);
+ mUidToPackageCache.remove(uid);
}
@Override
@@ -666,6 +696,7 @@
mTimingSessions.delete(userId);
mInQuotaAlarmListeners.delete(userId);
mExecutionStatsCache.delete(userId);
+ mUidToPackageCache.clear();
}
private boolean isUidInForeground(int uid) {
@@ -678,7 +709,7 @@
}
/** @return true if the job was started while the app was in the TOP state. */
- private boolean isTopStartedJob(@NonNull final JobStatus jobStatus) {
+ private boolean isTopStartedJobLocked(@NonNull final JobStatus jobStatus) {
return mTopStartedJobs.contains(jobStatus);
}
@@ -695,14 +726,14 @@
return jobStatus.getStandbyBucket();
}
- private boolean isWithinQuotaLocked(@NonNull final JobStatus jobStatus) {
+ @VisibleForTesting
+ boolean isWithinQuotaLocked(@NonNull final JobStatus jobStatus) {
final int standbyBucket = getEffectiveStandbyBucket(jobStatus);
- Timer timer = mPkgTimers.get(jobStatus.getSourceUserId(), jobStatus.getSourcePackageName());
// A job is within quota if one of the following is true:
// 1. it was started while the app was in the TOP state
// 2. the app is currently in the foreground
// 3. the app overall is within its quota
- return isTopStartedJob(jobStatus)
+ return isTopStartedJobLocked(jobStatus)
|| isUidInForeground(jobStatus.getSourceUid())
|| isWithinQuotaLocked(
jobStatus.getSourceUserId(), jobStatus.getSourcePackageName(), standbyBucket);
@@ -1081,7 +1112,9 @@
if (earliestEndElapsed == Long.MAX_VALUE) {
// Couldn't find a good time to clean up. Maybe this was called after we deleted all
// timing sessions.
- if (DEBUG) Slog.d(TAG, "Didn't find a time to schedule cleanup");
+ if (DEBUG) {
+ Slog.d(TAG, "Didn't find a time to schedule cleanup");
+ }
return;
}
// Need to keep sessions for all apps up to the max period, regardless of their current
@@ -1095,15 +1128,19 @@
mNextCleanupTimeElapsed = nextCleanupElapsed;
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, nextCleanupElapsed, ALARM_TAG_CLEANUP,
mSessionCleanupAlarmListener, mHandler);
- if (DEBUG) Slog.d(TAG, "Scheduled next cleanup for " + mNextCleanupTimeElapsed);
+ if (DEBUG) {
+ Slog.d(TAG, "Scheduled next cleanup for " + mNextCleanupTimeElapsed);
+ }
}
private void handleNewChargingStateLocked() {
final long nowElapsed = sElapsedRealtimeClock.millis();
final boolean isCharging = mChargeTracker.isCharging();
- if (DEBUG) Slog.d(TAG, "handleNewChargingStateLocked: " + isCharging);
+ if (DEBUG) {
+ Slog.d(TAG, "handleNewChargingStateLocked: " + isCharging);
+ }
// Deal with Timers first.
- mPkgTimers.forEach((t) -> t.onStateChanged(nowElapsed, isCharging));
+ mPkgTimers.forEach((t) -> t.onStateChangedLocked(nowElapsed, isCharging));
// Now update jobs.
maybeUpdateAllConstraintsLocked();
}
@@ -1140,7 +1177,7 @@
boolean changed = false;
for (int i = jobs.size() - 1; i >= 0; --i) {
final JobStatus js = jobs.valueAt(i);
- if (isTopStartedJob(js)) {
+ if (isTopStartedJobLocked(js)) {
// Job was started while the app was in the TOP state so we should allow it to
// finish.
changed |= js.setQuotaConstraintSatisfied(true);
@@ -1282,7 +1319,9 @@
if (!alarmListener.isWaiting()
|| inQuotaTimeElapsed < alarmListener.getTriggerTimeElapsed() - 3 * MINUTE_IN_MILLIS
|| alarmListener.getTriggerTimeElapsed() < inQuotaTimeElapsed) {
- if (DEBUG) Slog.d(TAG, "Scheduling start alarm for " + pkgString);
+ if (DEBUG) {
+ Slog.d(TAG, "Scheduling start alarm for " + pkgString);
+ }
// If the next time this app will have quota is at least 3 minutes before the
// alarm is supposed to go off, reschedule the alarm.
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, inQuotaTimeElapsed,
@@ -1430,8 +1469,8 @@
mUid = uid;
}
- void startTrackingJob(@NonNull JobStatus jobStatus) {
- if (isTopStartedJob(jobStatus)) {
+ void startTrackingJobLocked(@NonNull JobStatus jobStatus) {
+ if (isTopStartedJobLocked(jobStatus)) {
// We intentionally don't pay attention to fg state changes after a TOP job has
// started.
if (DEBUG) {
@@ -1440,27 +1479,28 @@
}
return;
}
- if (DEBUG) Slog.v(TAG, "Starting to track " + jobStatus.toShortString());
- synchronized (mLock) {
- // Always track jobs, even when charging.
- mRunningBgJobs.add(jobStatus);
- if (shouldTrackLocked()) {
- mBgJobCount++;
- incrementJobCount(mPkg.userId, mPkg.packageName, 1);
- if (mRunningBgJobs.size() == 1) {
- // Started tracking the first job.
- mStartTimeElapsed = sElapsedRealtimeClock.millis();
- // Starting the timer means that all cached execution stats are now
- // incorrect.
- invalidateAllExecutionStatsLocked(mPkg.userId, mPkg.packageName);
- scheduleCutoff();
- }
+ if (DEBUG) {
+ Slog.v(TAG, "Starting to track " + jobStatus.toShortString());
+ }
+ // Always track jobs, even when charging.
+ mRunningBgJobs.add(jobStatus);
+ if (shouldTrackLocked()) {
+ mBgJobCount++;
+ incrementJobCount(mPkg.userId, mPkg.packageName, 1);
+ if (mRunningBgJobs.size() == 1) {
+ // Started tracking the first job.
+ mStartTimeElapsed = sElapsedRealtimeClock.millis();
+ // Starting the timer means that all cached execution stats are now incorrect.
+ invalidateAllExecutionStatsLocked(mPkg.userId, mPkg.packageName);
+ scheduleCutoff();
}
}
}
void stopTrackingJob(@NonNull JobStatus jobStatus) {
- if (DEBUG) Slog.v(TAG, "Stopping tracking of " + jobStatus.toShortString());
+ if (DEBUG) {
+ Slog.v(TAG, "Stopping tracking of " + jobStatus.toShortString());
+ }
synchronized (mLock) {
if (mRunningBgJobs.size() == 0) {
// maybeStopTrackingJobLocked can be called when an app cancels a job, so a
@@ -1482,7 +1522,7 @@
* Stops tracking all jobs and cancels any pending alarms. This should only be called if
* the Timer is not going to be used anymore.
*/
- void dropEverything() {
+ void dropEverythingLocked() {
mRunningBgJobs.clear();
cancelCutoff();
}
@@ -1531,25 +1571,23 @@
return !mChargeTracker.isCharging() && !mForegroundUids.get(mUid);
}
- void onStateChanged(long nowElapsed, boolean isQuotaFree) {
- synchronized (mLock) {
- if (isQuotaFree) {
- emitSessionLocked(nowElapsed);
- } else if (shouldTrackLocked()) {
- // Start timing from unplug.
- if (mRunningBgJobs.size() > 0) {
- mStartTimeElapsed = nowElapsed;
- // NOTE: this does have the unfortunate consequence that if the device is
- // repeatedly plugged in and unplugged, or an app changes foreground state
- // very frequently, the job count for a package may be artificially high.
- mBgJobCount = mRunningBgJobs.size();
- incrementJobCount(mPkg.userId, mPkg.packageName, mBgJobCount);
- // Starting the timer means that all cached execution stats are now
- // incorrect.
- invalidateAllExecutionStatsLocked(mPkg.userId, mPkg.packageName);
- // Schedule cutoff since we're now actively tracking for quotas again.
- scheduleCutoff();
- }
+ void onStateChangedLocked(long nowElapsed, boolean isQuotaFree) {
+ if (isQuotaFree) {
+ emitSessionLocked(nowElapsed);
+ } else if (!isActive() && shouldTrackLocked()) {
+ // Start timing from unplug.
+ if (mRunningBgJobs.size() > 0) {
+ mStartTimeElapsed = nowElapsed;
+ // NOTE: this does have the unfortunate consequence that if the device is
+ // repeatedly plugged in and unplugged, or an app changes foreground state
+ // very frequently, the job count for a package may be artificially high.
+ mBgJobCount = mRunningBgJobs.size();
+ incrementJobCount(mPkg.userId, mPkg.packageName, mBgJobCount);
+ // Starting the timer means that all cached execution stats are now
+ // incorrect.
+ invalidateAllExecutionStatsLocked(mPkg.userId, mPkg.packageName);
+ // Schedule cutoff since we're now actively tracking for quotas again.
+ scheduleCutoff();
}
}
}
@@ -1604,7 +1642,6 @@
pw.println(js.toShortString());
}
}
-
pw.decreaseIndent();
}
@@ -1667,7 +1704,9 @@
@Override
public void onParoleStateChanged(final boolean isParoleOn) {
mInParole = isParoleOn;
- if (DEBUG) Slog.i(TAG, "Global parole state now " + (isParoleOn ? "ON" : "OFF"));
+ if (DEBUG) {
+ Slog.i(TAG, "Global parole state now " + (isParoleOn ? "ON" : "OFF"));
+ }
// Update job bookkeeping out of band.
BackgroundThread.getHandler().post(() -> {
synchronized (mLock) {
@@ -1712,7 +1751,9 @@
switch (msg.what) {
case MSG_REACHED_QUOTA: {
Package pkg = (Package) msg.obj;
- if (DEBUG) Slog.d(TAG, "Checking if " + pkg + " has reached its quota.");
+ if (DEBUG) {
+ Slog.d(TAG, "Checking if " + pkg + " has reached its quota.");
+ }
long timeRemainingMs = getRemainingExecutionTimeLocked(pkg.userId,
pkg.packageName);
@@ -1737,7 +1778,9 @@
break;
}
case MSG_CLEAN_UP_SESSIONS:
- if (DEBUG) Slog.d(TAG, "Cleaning up timing sessions.");
+ if (DEBUG) {
+ Slog.d(TAG, "Cleaning up timing sessions.");
+ }
deleteObsoleteSessionsLocked();
maybeScheduleCleanupAlarmLocked();
@@ -1745,7 +1788,9 @@
case MSG_CHECK_PACKAGE: {
String packageName = (String) msg.obj;
int userId = msg.arg1;
- if (DEBUG) Slog.d(TAG, "Checking pkg " + string(userId, packageName));
+ if (DEBUG) {
+ Slog.d(TAG, "Checking pkg " + string(userId, packageName));
+ }
if (maybeUpdateConstraintForPkgLocked(userId, packageName)) {
mStateChangedListener.onControllerStateChanged();
}
@@ -1767,13 +1812,28 @@
isQuotaFree = false;
}
// Update Timers first.
- final int userIndex = mPkgTimers.indexOfKey(userId);
- if (userIndex != -1) {
- final int numPkgs = mPkgTimers.numPackagesForUser(userId);
- for (int p = 0; p < numPkgs; ++p) {
- Timer t = mPkgTimers.valueAt(userIndex, p);
- if (t != null) {
- t.onStateChanged(nowElapsed, isQuotaFree);
+ if (mPkgTimers.indexOfKey(userId) >= 0) {
+ ArraySet<String> packages = mUidToPackageCache.get(uid);
+ if (packages == null) {
+ try {
+ String[] pkgs = AppGlobals.getPackageManager()
+ .getPackagesForUid(uid);
+ if (pkgs != null) {
+ for (String pkg : pkgs) {
+ mUidToPackageCache.add(uid, pkg);
+ }
+ packages = mUidToPackageCache.get(uid);
+ }
+ } catch (RemoteException e) {
+ Slog.wtf(TAG, "Failed to get package list", e);
+ }
+ }
+ if (packages != null) {
+ for (int i = packages.size() - 1; i >= 0; --i) {
+ Timer t = mPkgTimers.get(userId, packages.valueAt(i));
+ if (t != null) {
+ t.onStateChangedLocked(nowElapsed, isQuotaFree);
+ }
}
}
}
@@ -1883,6 +1943,17 @@
pw.println(mForegroundUids.toString());
pw.println();
+ pw.println("Cached UID->package map:");
+ pw.increaseIndent();
+ for (int i = 0; i < mUidToPackageCache.size(); ++i) {
+ final int uid = mUidToPackageCache.keyAt(i);
+ pw.print(uid);
+ pw.print(": ");
+ pw.println(mUidToPackageCache.get(uid));
+ }
+ pw.decreaseIndent();
+ pw.println();
+
mTrackedJobs.forEach((jobs) -> {
for (int j = 0; j < jobs.size(); j++) {
final JobStatus js = jobs.valueAt(j);
@@ -1936,6 +2007,29 @@
}
}
}
+
+ pw.println("Cached execution stats:");
+ pw.increaseIndent();
+ for (int u = 0; u < mExecutionStatsCache.numUsers(); ++u) {
+ final int userId = mExecutionStatsCache.keyAt(u);
+ for (int p = 0; p < mExecutionStatsCache.numPackagesForUser(userId); ++p) {
+ final String pkgName = mExecutionStatsCache.keyAt(u, p);
+ ExecutionStats[] stats = mExecutionStatsCache.valueAt(u, p);
+
+ pw.println(string(userId, pkgName));
+ pw.increaseIndent();
+ for (int i = 0; i < stats.length; ++i) {
+ ExecutionStats executionStats = stats[i];
+ if (executionStats != null) {
+ pw.print(JobStatus.bucketName(i));
+ pw.print(": ");
+ pw.println(executionStats);
+ }
+ }
+ pw.decreaseIndent();
+ }
+ }
+ pw.decreaseIndent();
}
@Override
@@ -1995,6 +2089,49 @@
}
}
+ ExecutionStats[] stats = mExecutionStatsCache.get(userId, pkgName);
+ if (stats != null) {
+ for (int bucketIndex = 0; bucketIndex < stats.length; ++bucketIndex) {
+ ExecutionStats es = stats[bucketIndex];
+ if (es == null) {
+ continue;
+ }
+ final long esToken = proto.start(
+ StateControllerProto.QuotaController.PackageStats.EXECUTION_STATS);
+ proto.write(
+ StateControllerProto.QuotaController.ExecutionStats.STANDBY_BUCKET,
+ bucketIndex);
+ proto.write(
+ StateControllerProto.QuotaController.ExecutionStats.EXPIRATION_TIME_ELAPSED,
+ es.expirationTimeElapsed);
+ proto.write(
+ StateControllerProto.QuotaController.ExecutionStats.WINDOW_SIZE_MS,
+ es.windowSizeMs);
+ proto.write(
+ StateControllerProto.QuotaController.ExecutionStats.EXECUTION_TIME_IN_WINDOW_MS,
+ es.executionTimeInWindowMs);
+ proto.write(
+ StateControllerProto.QuotaController.ExecutionStats.BG_JOB_COUNT_IN_WINDOW,
+ es.bgJobCountInWindow);
+ proto.write(
+ StateControllerProto.QuotaController.ExecutionStats.EXECUTION_TIME_IN_MAX_PERIOD_MS,
+ es.executionTimeInMaxPeriodMs);
+ proto.write(
+ StateControllerProto.QuotaController.ExecutionStats.BG_JOB_COUNT_IN_MAX_PERIOD,
+ es.bgJobCountInMaxPeriod);
+ proto.write(
+ StateControllerProto.QuotaController.ExecutionStats.QUOTA_CUTOFF_TIME_ELAPSED,
+ es.quotaCutoffTimeElapsed);
+ proto.write(
+ StateControllerProto.QuotaController.ExecutionStats.JOB_COUNT_EXPIRATION_TIME_ELAPSED,
+ es.jobCountExpirationTimeElapsed);
+ proto.write(
+ StateControllerProto.QuotaController.ExecutionStats.JOB_COUNT_IN_ALLOWED_TIME,
+ es.jobCountInAllowedTime);
+ proto.end(esToken);
+ }
+ }
+
proto.end(psToken);
}
}
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 1edb93a..27f3387 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -455,7 +455,8 @@
// Add in all the apps for every user/profile.
for (UserInfo profile : users) {
List<PackageInfo> pi =
- pm.getInstalledPackagesAsUser(PackageManager.MATCH_KNOWN_PACKAGES, profile.id);
+ pm.getInstalledPackagesAsUser(PackageManager.MATCH_KNOWN_PACKAGES
+ | PackageManager.MATCH_APEX, profile.id);
for (int j = 0; j < pi.size(); j++) {
if (pi.get(j).applicationInfo != null) {
String installer;
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 10afbef..0891ba4 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -99,7 +99,7 @@
* data for Tron, logcat, event logs and {@link android.app.WaitResult}.
*
* Tests:
- * atest CtsActivityManagerDeviceTestCases:ActivityMetricsLoggerTests
+ * atest CtsWindowManagerDeviceTestCases:ActivityMetricsLoggerTests
*/
class ActivityMetricsLogger {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index ee6cf54..0820b0d 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3372,6 +3372,11 @@
if (stack.inFreeformWindowingMode()) {
stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ } else if (stack.getParent().inFreeformWindowingMode()) {
+ // If the window is on a freeform display, set it to undefined. It will be
+ // resolved to freeform and it can adjust windowing mode when the display mode
+ // changes in runtime.
+ stack.setWindowingMode(WINDOWING_MODE_UNDEFINED);
} else {
stack.setWindowingMode(WINDOWING_MODE_FREEFORM);
}
diff --git a/services/core/java/com/android/server/wm/Dimmer.java b/services/core/java/com/android/server/wm/Dimmer.java
index a7a793f..767327a 100644
--- a/services/core/java/com/android/server/wm/Dimmer.java
+++ b/services/core/java/com/android/server/wm/Dimmer.java
@@ -102,7 +102,9 @@
}
void removeSurface() {
- getPendingTransaction().remove(mDimLayer);
+ if (mDimLayer != null && mDimLayer.isValid()) {
+ getPendingTransaction().remove(mDimLayer);
+ }
mDimLayer = null;
}
}
@@ -305,7 +307,9 @@
if (!mDimState.mDimming) {
if (!mDimState.mAnimateExit) {
- t.remove(mDimState.mDimLayer);
+ if (mDimState.mDimLayer.isValid()) {
+ t.remove(mDimState.mDimLayer);
+ }
} else {
startDimExit(mLastRequestedDimContainer, mDimState.mSurfaceAnimator, t);
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index bd874ba..a57dd6d 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -822,6 +822,10 @@
(int) attrs.hideTimeoutMilliseconds,
AccessibilityManager.FLAG_CONTENT_TEXT);
attrs.windowAnimations = com.android.internal.R.style.Animation_Toast;
+ // Toast can show with below conditions when the screen is locked.
+ if (canToastShowWhenLocked(callingPid)) {
+ attrs.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
+ }
break;
}
@@ -832,6 +836,16 @@
}
/**
+ * @return {@code true} if the calling activity initiate toast and is visible with
+ * {@link WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} flag.
+ */
+ boolean canToastShowWhenLocked(int callingPid) {
+ return mDisplayContent.forAllWindows(w -> {
+ return callingPid == w.mSession.mPid && w.isVisible() && w.canShowWhenLocked();
+ }, true /* traverseTopToBottom */);
+ }
+
+ /**
* Preflight adding a window to the system.
*
* Currently enforces that three window types are singletons per display:
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index eb919eb..12b62b9 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -23,6 +23,7 @@
import static com.android.server.am.ActivityManagerService.MY_PID;
import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
+import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
@@ -98,7 +99,7 @@
private final ActivityTaskManagerService mAtm;
// The actual proc... may be null only if 'persistent' is true (in which case we are in the
// process of launching the app)
- private volatile IApplicationThread mThread;
+ private IApplicationThread mThread;
// Currently desired scheduling class
private volatile int mCurSchedGroup;
// Currently computed process state
@@ -192,8 +193,11 @@
return mPid;
}
+ @HotPath(caller = HotPath.PROCESS_CHANGE)
public void setThread(IApplicationThread thread) {
- mThread = thread;
+ synchronized (mAtm.mGlobalLockWithoutBoost) {
+ mThread = thread;
+ }
}
IApplicationThread getThread() {
@@ -507,7 +511,14 @@
continue;
}
ActivityRecord topActivity = task.getTopActivity();
- if (topActivity != null && topActivity.visible) {
+ if (topActivity == null) {
+ continue;
+ }
+ // If an activity has just been started it will not yet be visible, but
+ // is expected to be soon. We treat this as if it were already visible.
+ // This ensures a subsequent activity can be started even before this one
+ // becomes visible.
+ if (topActivity.visible || topActivity.isState(INITIALIZING)) {
return true;
}
}
diff --git a/services/net/Android.bp b/services/net/Android.bp
index f73a285..d72f1cf 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -3,8 +3,6 @@
name: "ipmemorystore-aidl-interfaces",
local_include_dir: "java",
srcs: [
- // TODO: Define and use a filegroup for these files, since they're also used in
- // networkstack-aidl-interfaces. This does not appear to work at the moment.
"java/android/net/IIpMemoryStore.aidl",
"java/android/net/IIpMemoryStoreCallbacks.aidl",
"java/android/net/ipmemorystore/**/*.aidl",
@@ -17,17 +15,16 @@
enabled: false,
},
},
- api_dir: "aidl/networkstack",
+ api_dir: "aidl/ipmemorystore",
+ versions: ["1"],
}
aidl_interface {
name: "networkstack-aidl-interfaces",
local_include_dir: "java",
- include_dirs: ["frameworks/base/core/java"], // For framework parcelables.
+ include_dirs: ["frameworks/base/core/java"], // For framework parcelables.
srcs: [
"java/android/net/DhcpResultsParcelable.aidl",
- "java/android/net/IIpMemoryStore.aidl",
- "java/android/net/IIpMemoryStoreCallbacks.aidl",
"java/android/net/INetworkMonitor.aidl",
"java/android/net/INetworkMonitorCallbacks.aidl",
"java/android/net/INetworkStackConnector.aidl",
@@ -41,7 +38,6 @@
"java/android/net/dhcp/IDhcpServerCallbacks.aidl",
"java/android/net/ip/IIpClient.aidl",
"java/android/net/ip/IIpClientCallbacks.aidl",
- "java/android/net/ipmemorystore/**/*.aidl",
],
backend: {
ndk: {
@@ -52,6 +48,8 @@
},
},
api_dir: "aidl/networkstack",
+ imports: ["ipmemorystore-aidl-interfaces"],
+ versions: ["1"],
}
java_library_static {
@@ -62,7 +60,7 @@
"ipmemorystore-client",
"netd_aidl_interface-java",
"networkstack-aidl-interfaces-java",
- ]
+ ],
}
java_library_static {
@@ -75,7 +73,7 @@
],
static_libs: [
"ipmemorystore-aidl-interfaces-java",
- ]
+ ],
}
filegroup {
diff --git a/services/net/aidl/ipmemorystore/1/android/net/IIpMemoryStore.aidl b/services/net/aidl/ipmemorystore/1/android/net/IIpMemoryStore.aidl
new file mode 100644
index 0000000..a8cbab2
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/IIpMemoryStore.aidl
@@ -0,0 +1,9 @@
+package android.net;
+interface IIpMemoryStore {
+ oneway void storeNetworkAttributes(String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void storeBlob(String l2Key, String clientId, String name, in android.net.ipmemorystore.Blob data, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void findL2Key(in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnL2KeyResponseListener listener);
+ oneway void isSameNetwork(String l2Key1, String l2Key2, android.net.ipmemorystore.IOnSameL3NetworkResponseListener listener);
+ oneway void retrieveNetworkAttributes(String l2Key, android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener listener);
+ oneway void retrieveBlob(String l2Key, String clientId, String name, android.net.ipmemorystore.IOnBlobRetrievedListener listener);
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/IIpMemoryStoreCallbacks.aidl b/services/net/aidl/ipmemorystore/1/android/net/IIpMemoryStoreCallbacks.aidl
new file mode 100644
index 0000000..cf02c26
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/IIpMemoryStoreCallbacks.aidl
@@ -0,0 +1,4 @@
+package android.net;
+interface IIpMemoryStoreCallbacks {
+ oneway void onIpMemoryStoreFetched(in android.net.IIpMemoryStore ipMemoryStore);
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/Blob.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/Blob.aidl
new file mode 100644
index 0000000..291dbef
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/Blob.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+parcelable Blob {
+ byte[] data;
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
new file mode 100644
index 0000000..52f40d4
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnBlobRetrievedListener {
+ oneway void onBlobRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in String name, in android.net.ipmemorystore.Blob data);
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
new file mode 100644
index 0000000..7853514
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnL2KeyResponseListener {
+ oneway void onL2KeyResponse(in android.net.ipmemorystore.StatusParcelable status, in String l2Key);
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
new file mode 100644
index 0000000..3dd2ae6
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnNetworkAttributesRetrievedListener {
+ oneway void onNetworkAttributesRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes);
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
new file mode 100644
index 0000000..46d4ecb
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnSameL3NetworkResponseListener {
+ oneway void onSameL3NetworkResponse(in android.net.ipmemorystore.StatusParcelable status, in android.net.ipmemorystore.SameL3NetworkResponseParcelable response);
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnStatusListener.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnStatusListener.aidl
new file mode 100644
index 0000000..54e654b
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnStatusListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnStatusListener {
+ oneway void onComplete(in android.net.ipmemorystore.StatusParcelable status);
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/NetworkAttributesParcelable.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
new file mode 100644
index 0000000..9531ea3
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
@@ -0,0 +1,8 @@
+package android.net.ipmemorystore;
+parcelable NetworkAttributesParcelable {
+ byte[] assignedV4Address;
+ long assignedV4AddressExpiry;
+ String groupHint;
+ android.net.ipmemorystore.Blob[] dnsAddresses;
+ int mtu;
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
new file mode 100644
index 0000000..414272b
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
@@ -0,0 +1,6 @@
+package android.net.ipmemorystore;
+parcelable SameL3NetworkResponseParcelable {
+ String l2Key1;
+ String l2Key2;
+ float confidence;
+}
diff --git a/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/StatusParcelable.aidl b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/StatusParcelable.aidl
new file mode 100644
index 0000000..92c6779
--- /dev/null
+++ b/services/net/aidl/ipmemorystore/1/android/net/ipmemorystore/StatusParcelable.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+parcelable StatusParcelable {
+ int resultCode;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/DhcpResultsParcelable.aidl b/services/net/aidl/networkstack/1/android/net/DhcpResultsParcelable.aidl
new file mode 100644
index 0000000..92b5345
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/DhcpResultsParcelable.aidl
@@ -0,0 +1,8 @@
+package android.net;
+parcelable DhcpResultsParcelable {
+ android.net.StaticIpConfiguration baseConfiguration;
+ int leaseDuration;
+ int mtu;
+ String serverAddress;
+ String vendorInfo;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/INetworkMonitor.aidl b/services/net/aidl/networkstack/1/android/net/INetworkMonitor.aidl
new file mode 100644
index 0000000..b19f522
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/INetworkMonitor.aidl
@@ -0,0 +1,17 @@
+package android.net;
+interface INetworkMonitor {
+ oneway void start();
+ oneway void launchCaptivePortalApp();
+ oneway void notifyCaptivePortalAppFinished(int response);
+ oneway void setAcceptPartialConnectivity();
+ oneway void forceReevaluation(int uid);
+ oneway void notifyPrivateDnsChanged(in android.net.PrivateDnsConfigParcel config);
+ oneway void notifyDnsResponse(int returnCode);
+ oneway void notifyNetworkConnected(in android.net.LinkProperties lp, in android.net.NetworkCapabilities nc);
+ oneway void notifyNetworkDisconnected();
+ oneway void notifyLinkPropertiesChanged(in android.net.LinkProperties lp);
+ oneway void notifyNetworkCapabilitiesChanged(in android.net.NetworkCapabilities nc);
+ const int NETWORK_TEST_RESULT_VALID = 0;
+ const int NETWORK_TEST_RESULT_INVALID = 1;
+ const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/INetworkMonitorCallbacks.aidl b/services/net/aidl/networkstack/1/android/net/INetworkMonitorCallbacks.aidl
new file mode 100644
index 0000000..ee9871d
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/INetworkMonitorCallbacks.aidl
@@ -0,0 +1,8 @@
+package android.net;
+interface INetworkMonitorCallbacks {
+ oneway void onNetworkMonitorCreated(in android.net.INetworkMonitor networkMonitor);
+ oneway void notifyNetworkTested(int testResult, @nullable String redirectUrl);
+ oneway void notifyPrivateDnsConfigResolved(in android.net.PrivateDnsConfigParcel config);
+ oneway void showProvisioningNotification(String action, String packageName);
+ oneway void hideProvisioningNotification();
+}
diff --git a/services/net/aidl/networkstack/1/android/net/INetworkStackConnector.aidl b/services/net/aidl/networkstack/1/android/net/INetworkStackConnector.aidl
new file mode 100644
index 0000000..7da11e4
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/INetworkStackConnector.aidl
@@ -0,0 +1,7 @@
+package android.net;
+interface INetworkStackConnector {
+ oneway void makeDhcpServer(in String ifName, in android.net.dhcp.DhcpServingParamsParcel params, in android.net.dhcp.IDhcpServerCallbacks cb);
+ oneway void makeNetworkMonitor(in android.net.Network network, String name, in android.net.INetworkMonitorCallbacks cb);
+ oneway void makeIpClient(in String ifName, in android.net.ip.IIpClientCallbacks callbacks);
+ oneway void fetchIpMemoryStore(in android.net.IIpMemoryStoreCallbacks cb);
+}
diff --git a/services/net/aidl/networkstack/1/android/net/INetworkStackStatusCallback.aidl b/services/net/aidl/networkstack/1/android/net/INetworkStackStatusCallback.aidl
new file mode 100644
index 0000000..f6ca6f7
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/INetworkStackStatusCallback.aidl
@@ -0,0 +1,4 @@
+package android.net;
+interface INetworkStackStatusCallback {
+ oneway void onStatusAvailable(int statusCode);
+}
diff --git a/services/net/aidl/networkstack/1/android/net/InitialConfigurationParcelable.aidl b/services/net/aidl/networkstack/1/android/net/InitialConfigurationParcelable.aidl
new file mode 100644
index 0000000..c80a787
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/InitialConfigurationParcelable.aidl
@@ -0,0 +1,7 @@
+package android.net;
+parcelable InitialConfigurationParcelable {
+ android.net.LinkAddress[] ipAddresses;
+ android.net.IpPrefix[] directlyConnectedRoutes;
+ String[] dnsServers;
+ String gateway;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/PrivateDnsConfigParcel.aidl b/services/net/aidl/networkstack/1/android/net/PrivateDnsConfigParcel.aidl
new file mode 100644
index 0000000..2de790b
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/PrivateDnsConfigParcel.aidl
@@ -0,0 +1,5 @@
+package android.net;
+parcelable PrivateDnsConfigParcel {
+ String hostname;
+ String[] ips;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/ProvisioningConfigurationParcelable.aidl b/services/net/aidl/networkstack/1/android/net/ProvisioningConfigurationParcelable.aidl
new file mode 100644
index 0000000..3a6c304
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/ProvisioningConfigurationParcelable.aidl
@@ -0,0 +1,15 @@
+package android.net;
+parcelable ProvisioningConfigurationParcelable {
+ boolean enableIPv4;
+ boolean enableIPv6;
+ boolean usingMultinetworkPolicyTracker;
+ boolean usingIpReachabilityMonitor;
+ int requestedPreDhcpActionMs;
+ android.net.InitialConfigurationParcelable initialConfig;
+ android.net.StaticIpConfiguration staticIpConfig;
+ android.net.apf.ApfCapabilities apfCapabilities;
+ int provisioningTimeoutMs;
+ int ipv6AddrGenMode;
+ android.net.Network network;
+ String displayName;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/TcpKeepalivePacketDataParcelable.aidl b/services/net/aidl/networkstack/1/android/net/TcpKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..e121c06
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,13 @@
+package android.net;
+parcelable TcpKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+ int seq;
+ int ack;
+ int rcvWnd;
+ int rcvWndScale;
+ int tos;
+ int ttl;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/dhcp/DhcpServingParamsParcel.aidl b/services/net/aidl/networkstack/1/android/net/dhcp/DhcpServingParamsParcel.aidl
new file mode 100644
index 0000000..67193ae
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/dhcp/DhcpServingParamsParcel.aidl
@@ -0,0 +1,11 @@
+package android.net.dhcp;
+parcelable DhcpServingParamsParcel {
+ int serverAddr;
+ int serverAddrPrefixLength;
+ int[] defaultRouters;
+ int[] dnsServers;
+ int[] excludedAddrs;
+ long dhcpLeaseTimeSecs;
+ int linkMtu;
+ boolean metered;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/dhcp/IDhcpServer.aidl b/services/net/aidl/networkstack/1/android/net/dhcp/IDhcpServer.aidl
new file mode 100644
index 0000000..9143158
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/dhcp/IDhcpServer.aidl
@@ -0,0 +1,10 @@
+package android.net.dhcp;
+interface IDhcpServer {
+ oneway void start(in android.net.INetworkStackStatusCallback cb);
+ oneway void updateParams(in android.net.dhcp.DhcpServingParamsParcel params, in android.net.INetworkStackStatusCallback cb);
+ oneway void stop(in android.net.INetworkStackStatusCallback cb);
+ const int STATUS_UNKNOWN = 0;
+ const int STATUS_SUCCESS = 1;
+ const int STATUS_INVALID_ARGUMENT = 2;
+ const int STATUS_UNKNOWN_ERROR = 3;
+}
diff --git a/services/net/aidl/networkstack/1/android/net/dhcp/IDhcpServerCallbacks.aidl b/services/net/aidl/networkstack/1/android/net/dhcp/IDhcpServerCallbacks.aidl
new file mode 100644
index 0000000..dcc4489
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/dhcp/IDhcpServerCallbacks.aidl
@@ -0,0 +1,4 @@
+package android.net.dhcp;
+interface IDhcpServerCallbacks {
+ oneway void onDhcpServerCreated(int statusCode, in android.net.dhcp.IDhcpServer server);
+}
diff --git a/services/net/aidl/networkstack/1/android/net/ip/IIpClient.aidl b/services/net/aidl/networkstack/1/android/net/ip/IIpClient.aidl
new file mode 100644
index 0000000..95a1574
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/ip/IIpClient.aidl
@@ -0,0 +1,14 @@
+package android.net.ip;
+interface IIpClient {
+ oneway void completedPreDhcpAction();
+ oneway void confirmConfiguration();
+ oneway void readPacketFilterComplete(in byte[] data);
+ oneway void shutdown();
+ oneway void startProvisioning(in android.net.ProvisioningConfigurationParcelable req);
+ oneway void stop();
+ oneway void setTcpBufferSizes(in String tcpBufferSizes);
+ oneway void setHttpProxy(in android.net.ProxyInfo proxyInfo);
+ oneway void setMulticastFilter(boolean enabled);
+ oneway void addKeepalivePacketFilter(int slot, in android.net.TcpKeepalivePacketDataParcelable pkt);
+ oneway void removeKeepalivePacketFilter(int slot);
+}
diff --git a/services/net/aidl/networkstack/1/android/net/ip/IIpClientCallbacks.aidl b/services/net/aidl/networkstack/1/android/net/ip/IIpClientCallbacks.aidl
new file mode 100644
index 0000000..d6bc808
--- /dev/null
+++ b/services/net/aidl/networkstack/1/android/net/ip/IIpClientCallbacks.aidl
@@ -0,0 +1,16 @@
+package android.net.ip;
+interface IIpClientCallbacks {
+ oneway void onIpClientCreated(in android.net.ip.IIpClient ipClient);
+ oneway void onPreDhcpAction();
+ oneway void onPostDhcpAction();
+ oneway void onNewDhcpResults(in android.net.DhcpResultsParcelable dhcpResults);
+ oneway void onProvisioningSuccess(in android.net.LinkProperties newLp);
+ oneway void onProvisioningFailure(in android.net.LinkProperties newLp);
+ oneway void onLinkPropertiesChange(in android.net.LinkProperties newLp);
+ oneway void onReachabilityLost(in String logMsg);
+ oneway void onQuit();
+ oneway void installPacketFilter(in byte[] filter);
+ oneway void startReadPacketFilter();
+ oneway void setFallbackMulticastFilter(boolean enabled);
+ oneway void setNeighborDiscoveryOffload(boolean enable);
+}
diff --git a/services/net/java/android/net/IpMemoryStore.java b/services/net/java/android/net/IpMemoryStore.java
index 9248299..4a115e6 100644
--- a/services/net/java/android/net/IpMemoryStore.java
+++ b/services/net/java/android/net/IpMemoryStore.java
@@ -41,6 +41,11 @@
public void onIpMemoryStoreFetched(final IIpMemoryStore memoryStore) {
mService.complete(memoryStore);
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
});
}
diff --git a/services/net/java/android/net/ip/IpClientUtil.java b/services/net/java/android/net/ip/IpClientUtil.java
index 90624e0..714ade1 100644
--- a/services/net/java/android/net/ip/IpClientUtil.java
+++ b/services/net/java/android/net/ip/IpClientUtil.java
@@ -175,6 +175,11 @@
public void setNeighborDiscoveryOffload(boolean enable) {
mCb.setNeighborDiscoveryOffload(enable);
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
}
/**
diff --git a/services/net/java/android/net/ip/IpServer.java b/services/net/java/android/net/ip/IpServer.java
index fc1128b..66884c6 100644
--- a/services/net/java/android/net/ip/IpServer.java
+++ b/services/net/java/android/net/ip/IpServer.java
@@ -277,6 +277,11 @@
}
public abstract void callback(int statusCode);
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
}
private class DhcpServerCallbacksImpl extends DhcpServerCallbacks {
diff --git a/services/net/java/android/net/ipmemorystore/OnBlobRetrievedListener.java b/services/net/java/android/net/ipmemorystore/OnBlobRetrievedListener.java
index 22978a2..a17483a 100644
--- a/services/net/java/android/net/ipmemorystore/OnBlobRetrievedListener.java
+++ b/services/net/java/android/net/ipmemorystore/OnBlobRetrievedListener.java
@@ -40,6 +40,11 @@
listener.onBlobRetrieved(new Status(statusParcelable), l2Key, name, blob);
}
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
};
}
}
diff --git a/services/net/java/android/net/ipmemorystore/OnL2KeyResponseListener.java b/services/net/java/android/net/ipmemorystore/OnL2KeyResponseListener.java
index 9e7c1c8..e608aec 100644
--- a/services/net/java/android/net/ipmemorystore/OnL2KeyResponseListener.java
+++ b/services/net/java/android/net/ipmemorystore/OnL2KeyResponseListener.java
@@ -40,6 +40,11 @@
listener.onL2KeyResponse(new Status(statusParcelable), l2Key);
}
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
};
}
}
diff --git a/services/net/java/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java b/services/net/java/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java
index 59da268..ca6f302 100644
--- a/services/net/java/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java
+++ b/services/net/java/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java
@@ -44,6 +44,11 @@
new NetworkAttributes(networkAttributesParcelable));
}
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
};
}
}
diff --git a/services/net/java/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java b/services/net/java/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java
index 0154fd2..67f8da8 100644
--- a/services/net/java/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java
+++ b/services/net/java/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java
@@ -43,6 +43,11 @@
new SameL3NetworkResponse(sameL3NetworkResponseParcelable));
}
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
};
}
}
diff --git a/services/net/java/android/net/ipmemorystore/OnStatusListener.java b/services/net/java/android/net/ipmemorystore/OnStatusListener.java
index 824b7b0..4262efd 100644
--- a/services/net/java/android/net/ipmemorystore/OnStatusListener.java
+++ b/services/net/java/android/net/ipmemorystore/OnStatusListener.java
@@ -39,6 +39,11 @@
listener.onComplete(new Status(statusParcelable));
}
}
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
};
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index 08f6a37..f492d13 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -58,6 +58,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManagerInternal;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
@@ -224,50 +225,55 @@
}
private void setProcessState(int procState) {
+ setProcessState(procState, mSourceUid);
+ }
+
+ private void setProcessState(int procState, int uid) {
try {
- doReturn(procState).when(mActivityMangerInternal).getUidProcessState(mSourceUid);
+ doReturn(procState).when(mActivityMangerInternal).getUidProcessState(uid);
SparseBooleanArray foregroundUids = mQuotaController.getForegroundUids();
spyOn(foregroundUids);
- mUidObserver.onUidStateChanged(mSourceUid, procState, 0);
+ mUidObserver.onUidStateChanged(uid, procState, 0);
if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
- verify(foregroundUids, timeout(SECOND_IN_MILLIS).times(1))
- .put(eq(mSourceUid), eq(true));
- assertTrue(foregroundUids.get(mSourceUid));
+ verify(foregroundUids, timeout(2 * SECOND_IN_MILLIS).times(1))
+ .put(eq(uid), eq(true));
+ assertTrue(foregroundUids.get(uid));
} else {
- verify(foregroundUids, timeout(SECOND_IN_MILLIS).times(1)).delete(eq(mSourceUid));
- assertFalse(foregroundUids.get(mSourceUid));
+ verify(foregroundUids, timeout(2 * SECOND_IN_MILLIS).times(1)).delete(eq(uid));
+ assertFalse(foregroundUids.get(uid));
}
} catch (RemoteException e) {
fail("registerUidObserver threw exception: " + e.getMessage());
}
}
- private void setStandbyBucket(int bucketIndex) {
- int bucket;
+ private int bucketIndexToUsageStatsBucket(int bucketIndex) {
switch (bucketIndex) {
case ACTIVE_INDEX:
- bucket = UsageStatsManager.STANDBY_BUCKET_ACTIVE;
- break;
+ return UsageStatsManager.STANDBY_BUCKET_ACTIVE;
case WORKING_INDEX:
- bucket = UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
- break;
+ return UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
case FREQUENT_INDEX:
- bucket = UsageStatsManager.STANDBY_BUCKET_FREQUENT;
- break;
+ return UsageStatsManager.STANDBY_BUCKET_FREQUENT;
case RARE_INDEX:
- bucket = UsageStatsManager.STANDBY_BUCKET_RARE;
- break;
+ return UsageStatsManager.STANDBY_BUCKET_RARE;
default:
- bucket = UsageStatsManager.STANDBY_BUCKET_NEVER;
+ return UsageStatsManager.STANDBY_BUCKET_NEVER;
}
+ }
+
+ private void setStandbyBucket(int bucketIndex) {
when(mUsageStatsManager.getAppStandbyBucket(eq(SOURCE_PACKAGE), eq(SOURCE_USER_ID),
- anyLong())).thenReturn(bucket);
+ anyLong())).thenReturn(bucketIndexToUsageStatsBucket(bucketIndex));
}
private void setStandbyBucket(int bucketIndex, JobStatus... jobs) {
setStandbyBucket(bucketIndex);
for (JobStatus job : jobs) {
job.setStandbyBucket(bucketIndex);
+ when(mUsageStatsManager.getAppStandbyBucket(
+ eq(job.getSourcePackageName()), eq(job.getSourceUserId()), anyLong()))
+ .thenReturn(bucketIndexToUsageStatsBucket(bucketIndex));
}
}
@@ -283,8 +289,13 @@
new ComponentName(mContext, "TestQuotaJobService"))
.setMinimumLatency(Math.abs(jobId) + 1)
.build();
+ return createJobStatus(testTag, SOURCE_PACKAGE, CALLING_UID, jobInfo);
+ }
+
+ private JobStatus createJobStatus(String testTag, String packageName, int callingUid,
+ JobInfo jobInfo) {
JobStatus js = JobStatus.createFromJobInfo(
- jobInfo, CALLING_UID, SOURCE_PACKAGE, SOURCE_USER_ID, testTag);
+ jobInfo, callingUid, packageName, SOURCE_USER_ID, testTag);
// Make sure tests aren't passing just because the default bucket is likely ACTIVE.
js.setStandbyBucket(FREQUENT_INDEX);
return js;
@@ -935,6 +946,115 @@
}
@Test
+ public void testIsWithinQuotaLocked_UnderDuration_UnderJobCount_MultiStateChange_BelowFGS() {
+ setDischarging();
+
+ JobStatus jobStatus = createJobStatus(
+ "testIsWithinQuotaLocked_UnderDuration_UnderJobCount_MultiStateChange_BelowFGS", 1);
+ setStandbyBucket(ACTIVE_INDEX, jobStatus);
+ setProcessState(ActivityManager.PROCESS_STATE_BACKUP);
+
+ mQuotaController.maybeStartTrackingJobLocked(jobStatus, null);
+ mQuotaController.prepareForExecutionLocked(jobStatus);
+ for (int i = 0; i < 20; ++i) {
+ advanceElapsedClock(SECOND_IN_MILLIS);
+ setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
+ setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+ }
+ mQuotaController.maybeStopTrackingJobLocked(jobStatus, null, false);
+
+ advanceElapsedClock(15 * SECOND_IN_MILLIS);
+
+ mQuotaController.maybeStartTrackingJobLocked(jobStatus, null);
+ mQuotaController.prepareForExecutionLocked(jobStatus);
+ for (int i = 0; i < 20; ++i) {
+ advanceElapsedClock(SECOND_IN_MILLIS);
+ setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
+ setProcessState(ActivityManager.PROCESS_STATE_RECEIVER);
+ }
+ mQuotaController.maybeStopTrackingJobLocked(jobStatus, null, false);
+
+ advanceElapsedClock(10 * MINUTE_IN_MILLIS + 30 * SECOND_IN_MILLIS);
+
+ assertEquals(2, mQuotaController.getExecutionStatsLocked(
+ SOURCE_USER_ID, SOURCE_PACKAGE, ACTIVE_INDEX).jobCountInAllowedTime);
+ assertTrue(mQuotaController.isWithinQuotaLocked(jobStatus));
+ }
+
+ @Test
+ public void testIsWithinQuotaLocked_UnderDuration_UnderJobCount_MultiStateChange_SeparateApps()
+ throws Exception {
+ setDischarging();
+
+ final String unaffectedPkgName = "com.android.unaffected";
+ final int unaffectedUid = 10987;
+ JobInfo unaffectedJobInfo = new JobInfo.Builder(1,
+ new ComponentName(unaffectedPkgName, "foo"))
+ .build();
+ JobStatus unaffected = createJobStatus(
+ "testIsWithinQuotaLocked_UnderDuration_UnderJobCount_MultiStateChange_SeparateApps",
+ unaffectedPkgName, unaffectedUid, unaffectedJobInfo);
+ setStandbyBucket(FREQUENT_INDEX, unaffected);
+ setProcessState(ActivityManager.PROCESS_STATE_SERVICE, unaffectedUid);
+
+ final String fgChangerPkgName = "com.android.foreground.changer";
+ final int fgChangerUid = 10234;
+ JobInfo fgChangerJobInfo = new JobInfo.Builder(2,
+ new ComponentName(fgChangerPkgName, "foo"))
+ .build();
+ JobStatus fgStateChanger = createJobStatus(
+ "testIsWithinQuotaLocked_UnderDuration_UnderJobCount_MultiStateChange_SeparateApps",
+ fgChangerPkgName, fgChangerUid, fgChangerJobInfo);
+ setStandbyBucket(ACTIVE_INDEX, fgStateChanger);
+ setProcessState(ActivityManager.PROCESS_STATE_BACKUP, fgChangerUid);
+
+ IPackageManager packageManager = AppGlobals.getPackageManager();
+ spyOn(packageManager);
+ doReturn(new String[]{unaffectedPkgName})
+ .when(packageManager).getPackagesForUid(unaffectedUid);
+ doReturn(new String[]{fgChangerPkgName})
+ .when(packageManager).getPackagesForUid(fgChangerUid);
+
+ mQuotaController.maybeStartTrackingJobLocked(unaffected, null);
+ mQuotaController.prepareForExecutionLocked(unaffected);
+
+ mQuotaController.maybeStartTrackingJobLocked(fgStateChanger, null);
+ mQuotaController.prepareForExecutionLocked(fgStateChanger);
+ for (int i = 0; i < 20; ++i) {
+ advanceElapsedClock(SECOND_IN_MILLIS);
+ setProcessState(ActivityManager.PROCESS_STATE_TOP, fgChangerUid);
+ setProcessState(ActivityManager.PROCESS_STATE_TOP_SLEEPING, fgChangerUid);
+ }
+ mQuotaController.maybeStopTrackingJobLocked(fgStateChanger, null, false);
+
+ advanceElapsedClock(15 * SECOND_IN_MILLIS);
+
+ mQuotaController.maybeStartTrackingJobLocked(fgStateChanger, null);
+ mQuotaController.prepareForExecutionLocked(fgStateChanger);
+ for (int i = 0; i < 20; ++i) {
+ advanceElapsedClock(SECOND_IN_MILLIS);
+ setProcessState(ActivityManager.PROCESS_STATE_TOP, fgChangerUid);
+ setProcessState(ActivityManager.PROCESS_STATE_TOP_SLEEPING, fgChangerUid);
+ }
+ mQuotaController.maybeStopTrackingJobLocked(fgStateChanger, null, false);
+
+ mQuotaController.maybeStopTrackingJobLocked(unaffected, null, false);
+
+ assertTrue(mQuotaController.isWithinQuotaLocked(unaffected));
+ assertFalse(mQuotaController.isWithinQuotaLocked(fgStateChanger));
+ assertEquals(1,
+ mQuotaController.getTimingSessions(SOURCE_USER_ID, unaffectedPkgName).size());
+ assertEquals(42,
+ mQuotaController.getTimingSessions(SOURCE_USER_ID, fgChangerPkgName).size());
+ for (int i = ACTIVE_INDEX; i < RARE_INDEX; ++i) {
+ assertEquals(42, mQuotaController.getExecutionStatsLocked(
+ SOURCE_USER_ID, fgChangerPkgName, i).jobCountInAllowedTime);
+ assertEquals(1, mQuotaController.getExecutionStatsLocked(
+ SOURCE_USER_ID, unaffectedPkgName, i).jobCountInAllowedTime);
+ }
+ }
+
+ @Test
public void testMaybeScheduleCleanupAlarmLocked() {
// No sessions saved yet.
mQuotaController.maybeScheduleCleanupAlarmLocked();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
index 5b32fe6..292a05b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DimmerTests.java
@@ -27,6 +27,7 @@
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.when;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
@@ -78,7 +79,9 @@
@Override
public SurfaceControl build() {
- return mock(SurfaceControl.class);
+ SurfaceControl mSc = mock(SurfaceControl.class);
+ when(mSc.isValid()).thenReturn(true);
+ return mSc;
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index 07dd93c..1684f97 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -22,13 +22,17 @@
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
@@ -38,6 +42,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;
@@ -232,4 +237,40 @@
displayRotation, Surface.ROTATION_0, Surface.ROTATION_90));
}
}
+
+ @Test
+ public void testShouldShowToastWhenScreenLocked() {
+ final DisplayPolicy policy = mDisplayContent.getDisplayPolicy();
+ final WindowState activity = createApplicationWindow();
+ final WindowState toast = createToastWindow();
+
+ synchronized (mWm.mGlobalLock) {
+ policy.adjustWindowParamsLw(
+ toast, toast.mAttrs, 0 /* callingPid */, 0 /* callingUid */);
+
+ assertTrue(policy.canToastShowWhenLocked(0 /* callingUid */));
+ assertNotEquals(0, toast.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED);
+ }
+ }
+
+ private WindowState createToastWindow() {
+ final WindowState win = createWindow(null, TYPE_TOAST, "Toast");
+ final WindowManager.LayoutParams attrs = win.mAttrs;
+ attrs.width = WRAP_CONTENT;
+ attrs.height = WRAP_CONTENT;
+ attrs.flags = FLAG_KEEP_SCREEN_ON | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE;
+ attrs.format = PixelFormat.TRANSLUCENT;
+ return win;
+ }
+
+ private WindowState createApplicationWindow() {
+ final WindowState win = createWindow(null, TYPE_APPLICATION, "Application");
+ final WindowManager.LayoutParams attrs = win.mAttrs;
+ attrs.width = MATCH_PARENT;
+ attrs.height = MATCH_PARENT;
+ attrs.flags = FLAG_SHOW_WHEN_LOCKED | FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR;
+ attrs.format = PixelFormat.OPAQUE;
+ win.mHasSurface = true;
+ return win;
+ }
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 33d5c04..26745a7 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1199,6 +1199,80 @@
public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string";
/**
+ * Override the SPN Display Condition 2 integer bits (lsb). B2, B1 is the last two bits of the
+ * spn display condition coding.
+ *
+ * The default value -1 mean this field is not config.
+ *
+ * B1 = 0: display of registered PLMN name not required when registered PLMN is either HPLMN
+ * or a PLMN in the service provider PLMN list (see EF_SPDI).
+ * B1 = 1: display of registered PLMN name required when registered PLMN is either HPLMN or a
+ * PLMN in the service provider PLMN list(see EF_SPDI).
+ * B2 = 0: display of the service provider name is required when registered PLMN is neither
+ * HPLMN nor a PLMN in the service provider PLMN list(see EF_SPDI).
+ * B2 = 1: display of the service provider name is not required when registered PLMN is neither
+ * HPLMN nor a PLMN in the service provider PLMN list(see EF_SPDI).
+ *
+ * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.12 EF_SPN.
+ * @hide
+ */
+ public static final String KEY_SPN_DISPLAY_CONDITION_OVERRIDE_INT =
+ "spn_display_condition_override_int";
+
+ /**
+ * Override the SPDI - an array of PLMN(MCC + MNC) strings.
+ *
+ * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.66 EF_SPDI.
+ * @hide
+ */
+ public static final String KEY_SPDI_OVERRIDE_STRING_ARRAY = "spdi_override_string_array";
+
+ /**
+ * Override the EHPLMNs - an array of PLMN(MCC + MNC) strings.
+ *
+ * To allow provision for multiple HPLMN codes, PLMN codes that are present within this list
+ * shall replace the HPLMN code derived from the IMSI for PLMN selection purposes.
+ *
+ * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.84 EF_EHPLMN
+ * Reference: 3GPP TS 23.122 v15.6.0 Section 1.2 Equivalent HPLMN list
+ * @hide
+ */
+ public static final String KEY_EHPLMN_OVERRIDE_STRING_ARRAY = "ehplmn_override_string_array";
+
+ /**
+ * Override the PNN - a string array of comma-separated alpha long and short names:
+ * "alpha_long1, alpha_short1".
+ *
+ * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.58 EF_PNN.
+ * @hide
+ */
+ public static final String KEY_PNN_OVERRIDE_STRING_ARRAY = "pnn_override_string_array";
+
+ /**
+ * A string array of OPL records, each with comma-delimited data fields as follows:
+ * "plmn1,lactac_start,lactac_end,index".
+ *
+ * Reference: 3GPP TS 31.102 v15.2.0 Section 4.2.59 EF_OPL.
+ * @hide
+ */
+ public static final String KEY_OPL_OVERRIDE_STRING_ARRAY = "opl_override_opl_string_array";
+
+ /**
+ * Allow ERI rules to select a carrier name display string when using 3gpp2 access technologies.
+ *
+ * @hide
+ */
+ public static final String KEY_ALLOW_ERI_BOOL = "allow_cdma_eri_bool";
+
+ /**
+ * If true, use the carrier display name(SPN and PLMN) from the carrier display name resolver.
+ *
+ * @hide
+ */
+ public static final String KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL =
+ "enable_carrier_display_name_resolver_bool";
+
+ /**
* String to override sim country iso.
* Sim country iso is based on sim MCC which is coarse and doesn't work with dual IMSI SIM where
* a SIM can have multiple MCC from different countries.
@@ -3023,6 +3097,13 @@
sDefaults.putBoolean(KEY_CONFIG_WIFI_DISABLE_IN_ECBM, false);
sDefaults.putBoolean(KEY_CARRIER_NAME_OVERRIDE_BOOL, false);
sDefaults.putString(KEY_CARRIER_NAME_STRING, "");
+ sDefaults.putInt(KEY_SPN_DISPLAY_CONDITION_OVERRIDE_INT, -1);
+ sDefaults.putStringArray(KEY_SPDI_OVERRIDE_STRING_ARRAY, null);
+ sDefaults.putStringArray(KEY_PNN_OVERRIDE_STRING_ARRAY, null);
+ sDefaults.putStringArray(KEY_OPL_OVERRIDE_STRING_ARRAY, null);
+ sDefaults.putStringArray(KEY_EHPLMN_OVERRIDE_STRING_ARRAY, null);
+ sDefaults.putBoolean(KEY_ALLOW_ERI_BOOL, false);
+ sDefaults.putBoolean(KEY_ENABLE_CARRIER_DISPLAY_NAME_RESOLVER_BOOL, false);
sDefaults.putString(KEY_SIM_COUNTRY_ISO_OVERRIDE_STRING, "");
sDefaults.putString(KEY_CARRIER_CALL_SCREENING_APP_STRING, "");
sDefaults.putString(KEY_CALL_REDIRECTION_SERVICE_COMPONENT_NAME_STRING, null);
diff --git a/telephony/java/android/telephony/CellSignalStrengthLte.java b/telephony/java/android/telephony/CellSignalStrengthLte.java
index 2272dc9..8336d1b 100644
--- a/telephony/java/android/telephony/CellSignalStrengthLte.java
+++ b/telephony/java/android/telephony/CellSignalStrengthLte.java
@@ -58,15 +58,15 @@
@UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
private int mSignalStrength; // To be removed
private int mRssi;
- @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
+ @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
private int mRsrp;
- @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
+ @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
private int mRsrq;
- @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
+ @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
private int mRssnr;
- @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
+ @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
private int mCqi;
- @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.O)
+ @UnsupportedAppUsage(maxTargetSdk = android.os.Build.VERSION_CODES.P)
private int mTimingAdvance;
private int mLevel;
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
index 3ff862c..689abed 100644
--- a/tests/net/Android.bp
+++ b/tests/net/Android.bp
@@ -49,7 +49,6 @@
"libselinux",
"libui",
"libutils",
- "libvintf",
"libvndksupport",
"libtinyxml2",
"libunwindstack",
diff --git a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt
index d983b65..f045369 100644
--- a/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt
+++ b/tests/net/java/com/android/server/LegacyTypeTrackerTest.kt
@@ -20,6 +20,8 @@
import android.net.ConnectivityManager.TYPE_MOBILE
import android.net.ConnectivityManager.TYPE_WIFI
import android.net.ConnectivityManager.TYPE_WIMAX
+import android.net.NetworkInfo.DetailedState.CONNECTED
+import android.net.NetworkInfo.DetailedState.DISCONNECTED
import androidx.test.filters.SmallTest
import androidx.test.runner.AndroidJUnit4
import com.android.server.ConnectivityService.LegacyTypeTracker
@@ -32,8 +34,12 @@
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mockito.doReturn
import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.verify
const val UNSUPPORTED_TYPE = TYPE_WIMAX
@@ -89,4 +95,20 @@
mTracker.add(UNSUPPORTED_TYPE, mobileNai)
assertNull(mTracker.getNetworkForType(UNSUPPORTED_TYPE))
}
+
+ @Test
+ fun testBroadcastOnDisconnect() {
+ val mobileNai1 = mock(NetworkAgentInfo::class.java)
+ val mobileNai2 = mock(NetworkAgentInfo::class.java)
+ doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai1)
+ mTracker.add(TYPE_MOBILE, mobileNai1)
+ verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, CONNECTED, TYPE_MOBILE)
+ reset(mMockService)
+ doReturn(false).`when`(mMockService).isDefaultNetwork(mobileNai2)
+ mTracker.add(TYPE_MOBILE, mobileNai2)
+ verify(mMockService, never()).sendLegacyNetworkBroadcast(any(), any(), anyInt())
+ mTracker.remove(TYPE_MOBILE, mobileNai1, false /* wasDefault */)
+ verify(mMockService).sendLegacyNetworkBroadcast(mobileNai1, DISCONNECTED, TYPE_MOBILE)
+ verify(mMockService).sendLegacyNetworkBroadcast(mobileNai2, CONNECTED, TYPE_MOBILE)
+ }
}
diff --git a/tests/net/smoketest/Android.bp b/tests/net/smoketest/Android.bp
new file mode 100644
index 0000000..ef1ad2c
--- /dev/null
+++ b/tests/net/smoketest/Android.bp
@@ -0,0 +1,17 @@
+// This test exists only because the jni_libs list for these tests is difficult to
+// maintain: the test itself only depends on libnetworkstatsfactorytestjni, but the test
+// fails to load that library unless *all* the dependencies of that library are explicitly
+// listed in jni_libs. This means that whenever any of the dependencies changes the test
+// starts failing and breaking presubmits in frameworks/base. We cannot easily put
+// FrameworksNetTests into global presubmit because they are at times flaky, but this
+// test is effectively empty beyond validating that the libraries load correctly, and
+// thus should be stable enough to put in global presubmit.
+//
+// TODO: remove this hack when there is a better solution for jni_libs that includes
+// dependent libraries.
+android_test {
+ name: "FrameworksNetSmokeTests",
+ defaults: ["FrameworksNetTests-jni-defaults"],
+ srcs: ["java/SmokeTest.java"],
+ test_suites: ["device-tests"],
+}
diff --git a/tests/net/smoketest/AndroidManifest.xml b/tests/net/smoketest/AndroidManifest.xml
new file mode 100644
index 0000000..f1b9feb
--- /dev/null
+++ b/tests/net/smoketest/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.tests.net.smoketest">
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.frameworks.tests.net.smoketest"
+ android:label="Frameworks Networking Smoke Tests" />
+</manifest>
diff --git a/tests/net/smoketest/AndroidTest.xml b/tests/net/smoketest/AndroidTest.xml
new file mode 100644
index 0000000..ac366e4
--- /dev/null
+++ b/tests/net/smoketest/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs Frameworks Networking Smoke Tests.">
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="FrameworksNetSmokeTests.apk" />
+ </target_preparer>
+
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-tag" value="FrameworksNetSmokeTests" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.frameworks.tests.net.smoketest" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/tests/net/smoketest/java/SmokeTest.java b/tests/net/smoketest/java/SmokeTest.java
new file mode 100644
index 0000000..7d6655f
--- /dev/null
+++ b/tests/net/smoketest/java/SmokeTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.net;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public final class SmokeTest {
+
+ @Test
+ public void testLoadJni() {
+ System.loadLibrary("networkstatsfactorytestjni");
+ assertEquals(0, 0x00);
+ }
+}