summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xapi/current.txt4
-rw-r--r--cmds/statsd/src/atoms.proto50
-rw-r--r--cmds/statsd/src/external/Perfetto.cpp4
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.cpp8
-rw-r--r--core/java/android/content/pm/PackageManager.java2
-rw-r--r--core/java/android/hardware/display/DisplayViewport.java6
-rw-r--r--core/java/android/hardware/usb/UsbManager.java17
-rw-r--r--core/java/android/os/Looper.java60
-rw-r--r--core/java/android/provider/Settings.java17
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java7
-rw-r--r--core/java/android/util/FeatureFlagUtils.java1
-rw-r--r--core/java/com/android/internal/os/LooperStats.java269
-rw-r--r--core/jni/android_hardware_display_DisplayViewport.cpp2
-rw-r--r--core/jni/android_view_InputDevice.cpp4
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java2
-rw-r--r--core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java331
-rw-r--r--graphics/java/android/graphics/Insets.java9
-rw-r--r--libs/input/Android.bp3
-rw-r--r--libs/input/PointerController.h1
-rw-r--r--libs/input/SpriteController.cpp4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java1
-rw-r--r--packages/SystemUI/res/values/config.xml7
-rw-r--r--packages/SystemUI/res/values/dimens.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java81
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java67
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java142
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/ScrimViewTest.java9
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java13
-rw-r--r--services/core/java/com/android/server/LooperStatsService.java135
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java12
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java3
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java21
-rw-r--r--services/core/java/com/android/server/stats/StatsCompanionService.java28
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java21
-rw-r--r--services/core/jni/com_android_server_input_InputManagerService.cpp26
-rw-r--r--services/java/com/android/server/SystemServer.java5
-rw-r--r--services/usb/java/com/android/server/usb/UsbAlsaManager.java58
-rw-r--r--services/usb/java/com/android/server/usb/UsbHandlerManager.java135
-rw-r--r--services/usb/java/com/android/server/usb/UsbHostManager.java6
-rw-r--r--services/usb/java/com/android/server/usb/UsbPermissionManager.java246
-rw-r--r--services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java56
-rw-r--r--services/usb/java/com/android/server/usb/UsbSettingsManager.java8
-rw-r--r--services/usb/java/com/android/server/usb/UsbUserSettingsManager.java247
-rw-r--r--tools/validatekeymaps/Android.bp1
-rw-r--r--tools/validatekeymaps/Main.cpp7
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java2
-rw-r--r--wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java8
52 files changed, 1599 insertions, 663 deletions
diff --git a/api/current.txt b/api/current.txt
index ebd4c9b6b5f9..8bdafa9c2755 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -11313,6 +11313,7 @@ package android.content.pm {
field public static final java.lang.String FEATURE_DEVICE_ADMIN = "android.software.device_admin";
field public static final java.lang.String FEATURE_EMBEDDED = "android.hardware.type.embedded";
field public static final java.lang.String FEATURE_ETHERNET = "android.hardware.ethernet";
+ field public static final java.lang.String FEATURE_FACE = "android.hardware.face";
field public static final java.lang.String FEATURE_FAKETOUCH = "android.hardware.faketouch";
field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT = "android.hardware.faketouch.multitouch.distinct";
field public static final java.lang.String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = "android.hardware.faketouch.multitouch.jazzhand";
@@ -11322,6 +11323,7 @@ package android.content.pm {
field public static final java.lang.String FEATURE_HIFI_SENSORS = "android.hardware.sensor.hifi_sensors";
field public static final java.lang.String FEATURE_HOME_SCREEN = "android.software.home_screen";
field public static final java.lang.String FEATURE_INPUT_METHODS = "android.software.input_methods";
+ field public static final java.lang.String FEATURE_IRIS = "android.hardware.iris";
field public static final java.lang.String FEATURE_LEANBACK = "android.software.leanback";
field public static final java.lang.String FEATURE_LEANBACK_ONLY = "android.software.leanback_only";
field public static final java.lang.String FEATURE_LIVE_TV = "android.software.live_tv";
@@ -13784,7 +13786,7 @@ package android.graphics {
field public static final int YV12 = 842094169; // 0x32315659
}
- public class Insets {
+ public final class Insets {
method public static android.graphics.Insets of(int, int, int, int);
method public static android.graphics.Insets of(android.graphics.Rect);
field public static final android.graphics.Insets NONE;
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 3c9f7eee10b6..2ecfbe733bca 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -133,7 +133,7 @@ message Atom {
}
// Pulled events will start at field 10000.
- // Next: 10024
+ // Next: 10025
oneof pulled {
WifiBytesTransfer wifi_bytes_transfer = 10000;
WifiBytesTransferByFgBg wifi_bytes_transfer_by_fg_bg = 10001;
@@ -159,6 +159,7 @@ message Atom {
Temperature temperature = 10021;
BinderCalls binder_calls = 10022;
BinderCallsExceptions binder_calls_exceptions = 10023;
+ LooperStats looper_stats = 10024;
}
// DO NOT USE field numbers above 100,000 in AOSP. Field numbers above
@@ -2203,3 +2204,50 @@ message BinderCallsExceptions {
// Total number of exceptions.
optional int64 exception_count = 2;
}
+
+message LooperStats {
+ // Currently not collected and always set to 0.
+ optional int32 uid = 1 [(is_uid) = true];
+
+ // Fully qualified class name of the handler target class.
+ //
+ // This field does not contain PII. This is a system server class name.
+ optional string handler_class_name = 2;
+
+ // The name of the thread that runs the Looper.
+ //
+ // This field does not contain PII. This is a system server thread name.
+ optional string looper_thread_name = 3;
+
+ // The name of the dispatched message.
+ //
+ // This field does not contain PII. This is a system server constant or class
+ // name.
+ optional string message_name = 4;
+
+ // Total number of successfully dispatched messages.
+ optional int64 message_count = 5;
+
+ // Total number of messages that failed dispatching.
+ optional int64 exception_count = 6;
+
+ // Total number of processed messages we have data recorded for. If we
+ // collected data for all the messages, message_count will be equal to
+ // recorded_message_count.
+ //
+ // If recorded_message_count is different than message_count, it means data
+ // collection has been sampled. All the fields below will be sampled in this
+ // case.
+ optional int64 recorded_message_count = 7;
+
+ // Total latency of all processed messages.
+ // Average can be computed using recorded_total_latency_micros /
+ // recorded_message_count.
+ optional int64 recorded_total_latency_micros = 8;
+
+ // Total CPU usage of all processed message.
+ // Average can be computed using recorded_total_cpu_micros /
+ // recorded_message_count. Total can be computed using
+ // recorded_total_cpu_micros / recorded_message_count * call_count.
+ optional int64 recorded_total_cpu_micros = 9;
+}
diff --git a/cmds/statsd/src/external/Perfetto.cpp b/cmds/statsd/src/external/Perfetto.cpp
index e44351b39769..42cc543f18a8 100644
--- a/cmds/statsd/src/external/Perfetto.cpp
+++ b/cmds/statsd/src/external/Perfetto.cpp
@@ -105,9 +105,9 @@ bool CollectPerfettoTraceAndUploadToDropbox(const PerfettoDetails& config,
readPipe.reset(); // Close the read end (owned by the child process).
- // Using fopen() because fwrite() has the right logic to chunking write()
+ // Using fdopen() because fwrite() has the right logic to chunking write()
// over a pipe (see __sfvwrite()).
- FILE* writePipeStream = fdopen(writePipe.get(), "wb");
+ FILE* writePipeStream = android::base::Fdopen(std::move(writePipe), "wb");
if (!writePipeStream) {
ALOGE("fdopen() failed while calling the Perfetto client: %s", strerror(errno));
return false;
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index e6e84550cf5f..28718823bb32 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -183,7 +183,13 @@ const std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = {
{{},
{},
1 * NS_PER_SEC,
- new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}}
+ new StatsCompanionServicePuller(android::util::BINDER_CALLS_EXCEPTIONS)}},
+ // looper_stats
+ {android::util::LOOPER_STATS,
+ {{5, 6, 7, 8, 9},
+ {2, 3, 4},
+ 1 * NS_PER_SEC,
+ new StatsCompanionServicePuller(android::util::LOOPER_STATS)}}
};
StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 7d8ff4c3d0c8..5b0e85632b90 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2274,7 +2274,6 @@ public abstract class PackageManager {
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device has biometric hardware to perform face authentication.
- * @hide
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_FACE = "android.hardware.face";
@@ -2282,7 +2281,6 @@ public abstract class PackageManager {
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: The device has biometric hardware to perform iris authentication.
- * @hide
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_IRIS = "android.hardware.iris";
diff --git a/core/java/android/hardware/display/DisplayViewport.java b/core/java/android/hardware/display/DisplayViewport.java
index b4955ea44288..496f34c0348a 100644
--- a/core/java/android/hardware/display/DisplayViewport.java
+++ b/core/java/android/hardware/display/DisplayViewport.java
@@ -30,6 +30,12 @@ import android.text.TextUtils;
* @hide Only for use within the system server.
*/
public final class DisplayViewport {
+
+ // Viewport constants defined in InputReader.h.
+ public static final int VIEWPORT_INTERNAL = 1;
+ public static final int VIEWPORT_EXTERNAL = 2;
+ public static final int VIEWPORT_VIRTUAL = 3;
+
// True if this viewport is valid.
public boolean valid;
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 3141be4e9e97..ae0855a684ed 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -300,6 +300,23 @@ public class UsbManager {
public static final String EXTRA_PERMISSION_GRANTED = "permission";
/**
+ * Name of extra added to start systemui.usb.UsbPermissionActivity
+ * containing package name of the app which requests USB permission.
+ *
+ * @hide
+ */
+ public static final String EXTRA_PACKAGE = "android.hardware.usb.extra.PACKAGE";
+
+ /**
+ * Name of extra added to start systemui.usb.UsbPermissionActivity
+ * containing the whether the app which requests USB permission can be set as default handler
+ * for USB device attach event or USB accessory attach event or not.
+ *
+ * @hide
+ */
+ public static final String EXTRA_CAN_BE_DEFAULT = "android.hardware.usb.extra.CAN_BE_DEFAULT";
+
+ /**
* Code for the charging usb function. Passed into {@link #setCurrentFunctions(long)}
* {@hide}
*/
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 684a8ee43c87..ded3a1983fb2 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -18,7 +18,6 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.LooperProto;
import android.util.Log;
import android.util.Printer;
import android.util.Slog;
@@ -70,6 +69,7 @@ public final class Looper {
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper; // guarded by Looper.class
+ private static Observer sObserver;
final MessageQueue mQueue;
final Thread mThread;
@@ -131,6 +131,15 @@ public final class Looper {
}
/**
+ * Set the transaction observer for all Loopers in this process.
+ *
+ * @hide
+ */
+ public static void setObserver(@Nullable Observer observer) {
+ sObserver = observer;
+ }
+
+ /**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
@@ -169,6 +178,8 @@ public final class Looper {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
+ // Make sure the observer won't change while processing a transaction.
+ final Observer observer = sObserver;
final long traceTag = me.mTraceTag;
long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;
@@ -189,9 +200,21 @@ public final class Looper {
final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;
final long dispatchEnd;
+ Object token = null;
+ if (observer != null) {
+ token = observer.messageDispatchStarting();
+ }
try {
msg.target.dispatchMessage(msg);
+ if (observer != null) {
+ observer.messageDispatched(token, msg);
+ }
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
+ } catch (Exception exception) {
+ if (observer != null) {
+ observer.dispatchingThrewException(token, msg, exception);
+ }
+ throw exception;
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
@@ -397,4 +420,39 @@ public final class Looper {
return "Looper (" + mThread.getName() + ", tid " + mThread.getId()
+ ") {" + Integer.toHexString(System.identityHashCode(this)) + "}";
}
+
+ /** {@hide} */
+ public interface Observer {
+ /**
+ * Called right before a message is dispatched.
+ *
+ * <p> The token type is not specified to allow the implementation to specify its own type.
+ *
+ * @return a token used for collecting telemetry when dispatching a single message.
+ * The token token must be passed back exactly once to either
+ * {@link Observer#messageDispatched} or {@link Observer#dispatchingThrewException}
+ * and must not be reused again.
+ *
+ */
+ Object messageDispatchStarting();
+
+ /**
+ * Called when a message was processed by a Handler.
+ *
+ * @param token Token obtained by previously calling
+ * {@link Observer#messageDispatchStarting} on the same Observer instance.
+ * @param msg The message that was dispatched.
+ */
+ void messageDispatched(Object token, Message msg);
+
+ /**
+ * Called when an exception was thrown while processing a message.
+ *
+ * @param token Token obtained by previously calling
+ * {@link Observer#messageDispatchStarting} on the same Observer instance.
+ * @param msg The message that was dispatched and caused an exception.
+ * @param exception The exception that was thrown.
+ */
+ void dispatchingThrewException(Object token, Message msg, Exception exception);
+ }
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a1cc67d661e3..71938d219ccc 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -13308,6 +13308,23 @@ public final class Settings {
* @hide
*/
public static final String BINDER_CALLS_STATS = "binder_calls_stats";
+
+ /**
+ * Default user id to boot into. They map to user ids, for example, 10, 11, 12.
+ *
+ * @hide
+ */
+ public static final String DEFAULT_USER_ID_TO_BOOT_INTO = "default_boot_into_user_id";
+
+ /**
+ * Persistent user id that is last logged in to.
+ *
+ * They map to user ids, for example, 10, 11, 12.
+ *
+ * @hide
+ */
+ public static final String LAST_ACTIVE_USER_ID = "last_active_persistent_user_id";
+
}
/**
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index febdb83f0af3..4bd86a44a8ed 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -164,8 +164,7 @@ public abstract class WallpaperService extends Service {
int mType;
int mCurWidth;
int mCurHeight;
- int mWindowFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- | WindowManager.LayoutParams.FLAG_SCALED;
+ int mWindowFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
int mWindowPrivateFlags =
WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS;
int mCurWindowFlags = mWindowFlags;
@@ -776,6 +775,7 @@ public abstract class WallpaperService extends Service {
mDisplay.getDisplayInfo(displayInfo);
mLayout.width = Math.max(displayInfo.logicalWidth, myWidth);
mLayout.height = Math.max(displayInfo.logicalHeight, myHeight);
+ mWindowFlags |= WindowManager.LayoutParams.FLAG_SCALED;
}
mLayout.format = mFormat;
@@ -785,8 +785,7 @@ public abstract class WallpaperService extends Service {
| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_SCALED;
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
mCurWindowPrivateFlags = mWindowPrivateFlags;
mLayout.privateFlags = mWindowPrivateFlags;
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index a7f14b6bf0c6..b5ade2a3b654 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -45,6 +45,7 @@ public class FeatureFlagUtils {
DEFAULT_FLAGS.put("settings_systemui_theme", "true");
DEFAULT_FLAGS.put("settings_dynamic_homepage", "false");
DEFAULT_FLAGS.put("settings_mobile_network_v2", "false");
+ DEFAULT_FLAGS.put("settings_data_usage_v2", "false");
DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "true");
}
diff --git a/core/java/com/android/internal/os/LooperStats.java b/core/java/com/android/internal/os/LooperStats.java
new file mode 100644
index 000000000000..edf475f1dba3
--- /dev/null
+++ b/core/java/com/android/internal/os/LooperStats.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.SystemClock;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * Collects aggregated telemetry data about Looper message dispatching.
+ *
+ * @hide Only for use within the system server.
+ */
+public class LooperStats implements Looper.Observer {
+ private static final int TOKEN_POOL_SIZE = 50;
+ private static final int DEFAULT_ENTRIES_SIZE_CAP = 2000;
+ private static final int DEFAULT_SAMPLING_INTERVAL = 100;
+
+ @GuardedBy("mLock")
+ private final SparseArray<Entry> mEntries = new SparseArray<>(256);
+ private final Object mLock = new Object();
+ private final Entry mOverflowEntry = new Entry("OVERFLOW");
+ private final Entry mHashCollisionEntry = new Entry("HASH_COLLISION");
+ private final ConcurrentLinkedQueue<DispatchSession> mSessionPool =
+ new ConcurrentLinkedQueue<>();
+ private final int mSamplingInterval;
+ private final int mEntriesSizeCap;
+
+ public LooperStats() {
+ this(DEFAULT_SAMPLING_INTERVAL, DEFAULT_ENTRIES_SIZE_CAP);
+ }
+
+ public LooperStats(int samplingInterval, int entriesSizeCap) {
+ this.mSamplingInterval = samplingInterval;
+ this.mEntriesSizeCap = entriesSizeCap;
+ }
+
+ @Override
+ public Object messageDispatchStarting() {
+ if (shouldCollectDetailedData()) {
+ DispatchSession session = mSessionPool.poll();
+ session = session == null ? new DispatchSession() : session;
+ session.startTimeMicro = getElapsedRealtimeMicro();
+ session.cpuStartMicro = getThreadTimeMicro();
+ return session;
+ }
+
+ return DispatchSession.NOT_SAMPLED;
+ }
+
+ @Override
+ public void messageDispatched(Object token, Message msg) {
+ DispatchSession session = (DispatchSession) token;
+ Entry entry = getOrCreateEntry(msg);
+ synchronized (entry) {
+ entry.messageCount++;
+ if (session != DispatchSession.NOT_SAMPLED) {
+ entry.recordedMessageCount++;
+ long latency = getElapsedRealtimeMicro() - session.startTimeMicro;
+ long cpuUsage = getThreadTimeMicro() - session.cpuStartMicro;
+ entry.totalLatencyMicro += latency;
+ entry.maxLatencyMicro = Math.max(entry.maxLatencyMicro, latency);
+ entry.cpuUsageMicro += cpuUsage;
+ entry.maxCpuUsageMicro = Math.max(entry.maxCpuUsageMicro, cpuUsage);
+ }
+ }
+
+ recycleSession(session);
+ }
+
+ @Override
+ public void dispatchingThrewException(Object token, Message msg, Exception exception) {
+ DispatchSession session = (DispatchSession) token;
+ Entry entry = getOrCreateEntry(msg);
+ synchronized (entry) {
+ entry.exceptionCount++;
+ }
+ recycleSession(session);
+ }
+
+ /** Returns an array of {@link ExportedEntry entries} with the aggregated statistics. */
+ public List<ExportedEntry> getEntries() {
+ final ArrayList<ExportedEntry> entries;
+ synchronized (mLock) {
+ final int size = mEntries.size();
+ entries = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ Entry entry = mEntries.valueAt(i);
+ synchronized (entry) {
+ entries.add(new ExportedEntry(entry));
+ }
+ }
+ }
+ // Add the overflow and collision entries only if they have any data.
+ if (mOverflowEntry.messageCount > 0 || mOverflowEntry.exceptionCount > 0) {
+ synchronized (mOverflowEntry) {
+ entries.add(new ExportedEntry(mOverflowEntry));
+ }
+ }
+ if (mHashCollisionEntry.messageCount > 0 || mHashCollisionEntry.exceptionCount > 0) {
+ synchronized (mHashCollisionEntry) {
+ entries.add(new ExportedEntry(mHashCollisionEntry));
+ }
+ }
+ return entries;
+ }
+
+ /** Removes all collected data. */
+ public void reset() {
+ synchronized (mLock) {
+ mEntries.clear();
+ }
+ synchronized (mHashCollisionEntry) {
+ mHashCollisionEntry.reset();
+ }
+ synchronized (mOverflowEntry) {
+ mOverflowEntry.reset();
+ }
+ }
+
+ @NonNull
+ private Entry getOrCreateEntry(Message msg) {
+ final int id = Entry.idFor(msg);
+ Entry entry;
+ synchronized (mLock) {
+ entry = mEntries.get(id);
+ if (entry == null) {
+ if (mEntries.size() >= mEntriesSizeCap) {
+ // If over the size cap, track totals under a single entry.
+ return mOverflowEntry;
+ }
+ entry = new Entry(msg);
+ mEntries.put(id, entry);
+ }
+ }
+
+ if (entry.handler.getClass() != msg.getTarget().getClass()
+ || entry.handler.getLooper().getThread()
+ != msg.getTarget().getLooper().getThread()) {
+ // If a hash collision happened, track totals under a single entry.
+ return mHashCollisionEntry;
+ }
+ return entry;
+ }
+
+ private void recycleSession(DispatchSession session) {
+ if (session != DispatchSession.NOT_SAMPLED && mSessionPool.size() < TOKEN_POOL_SIZE) {
+ mSessionPool.add(session);
+ }
+ }
+
+ protected long getThreadTimeMicro() {
+ return SystemClock.currentThreadTimeMicro();
+ }
+
+ protected long getElapsedRealtimeMicro() {
+ return SystemClock.elapsedRealtimeNanos() / 1000;
+ }
+
+ protected boolean shouldCollectDetailedData() {
+ return ThreadLocalRandom.current().nextInt() % mSamplingInterval == 0;
+ }
+
+ private static class DispatchSession {
+ static final DispatchSession NOT_SAMPLED = new DispatchSession();
+ public long startTimeMicro;
+ public long cpuStartMicro;
+ }
+
+ private static class Entry {
+ public final Handler handler;
+ public final String messageName;
+ public long messageCount;
+ public long recordedMessageCount;
+ public long exceptionCount;
+ public long totalLatencyMicro;
+ public long maxLatencyMicro;
+ public long cpuUsageMicro;
+ public long maxCpuUsageMicro;
+
+ Entry(Message msg) {
+ handler = msg.getTarget();
+ messageName = handler.getMessageName(msg);
+ }
+
+ Entry(String specialEntryName) {
+ handler = null;
+ messageName = specialEntryName;
+ }
+
+ void reset() {
+ messageCount = 0;
+ recordedMessageCount = 0;
+ exceptionCount = 0;
+ totalLatencyMicro = 0;
+ maxLatencyMicro = 0;
+ cpuUsageMicro = 0;
+ maxCpuUsageMicro = 0;
+ }
+
+ static int idFor(Message msg) {
+ int result = 7;
+ result = 31 * result + msg.getTarget().getLooper().getThread().hashCode();
+ result = 31 * result + msg.getTarget().getClass().hashCode();
+ if (msg.getCallback() != null) {
+ return 31 * result + msg.getCallback().getClass().hashCode();
+ } else {
+ return 31 * result + msg.what;
+ }
+ }
+ }
+
+ /** Aggregated data of Looper message dispatching in the in the current process. */
+ public static class ExportedEntry {
+ public final String handlerClassName;
+ public final String threadName;
+ public final String messageName;
+ public final long messageCount;
+ public final long recordedMessageCount;
+ public final long exceptionCount;
+ public final long totalLatencyMicros;
+ public final long maxLatencyMicros;
+ public final long cpuUsageMicros;
+ public final long maxCpuUsageMicros;
+
+ ExportedEntry(Entry entry) {
+ if (entry.handler != null) {
+ this.handlerClassName = entry.handler.getClass().getName();
+ this.threadName = entry.handler.getLooper().getThread().getName();
+ } else {
+ // Overflow/collision entries do not have a handler set.
+ this.handlerClassName = "";
+ this.threadName = "";
+ }
+ this.messageName = entry.messageName;
+ this.messageCount = entry.messageCount;
+ this.recordedMessageCount = entry.recordedMessageCount;
+ this.exceptionCount = entry.exceptionCount;
+ this.totalLatencyMicros = entry.totalLatencyMicro;
+ this.maxLatencyMicros = entry.maxLatencyMicro;
+ this.cpuUsageMicros = entry.cpuUsageMicro;
+ this.maxCpuUsageMicros = entry.maxCpuUsageMicro;
+ }
+ }
+}
diff --git a/core/jni/android_hardware_display_DisplayViewport.cpp b/core/jni/android_hardware_display_DisplayViewport.cpp
index 23c3877e1200..ab8e685d5441 100644
--- a/core/jni/android_hardware_display_DisplayViewport.cpp
+++ b/core/jni/android_hardware_display_DisplayViewport.cpp
@@ -61,7 +61,7 @@ status_t android_hardware_display_DisplayViewport_toNative(JNIEnv* env, jobject
jstring uniqueId =
jstring(env->GetObjectField(viewportObj, gDisplayViewportClassInfo.uniqueId));
if (uniqueId != nullptr) {
- viewport->uniqueId.setTo(ScopedUtfChars(env, uniqueId).c_str());
+ viewport->uniqueId = ScopedUtfChars(env, uniqueId).c_str();
}
jobject logicalFrameObj =
diff --git a/core/jni/android_view_InputDevice.cpp b/core/jni/android_view_InputDevice.cpp
index 494fad7900ef..a698d66965e4 100644
--- a/core/jni/android_view_InputDevice.cpp
+++ b/core/jni/android_view_InputDevice.cpp
@@ -37,13 +37,13 @@ static struct {
} gInputDeviceClassInfo;
jobject android_view_InputDevice_create(JNIEnv* env, const InputDeviceInfo& deviceInfo) {
- ScopedLocalRef<jstring> nameObj(env, env->NewStringUTF(deviceInfo.getDisplayName().string()));
+ ScopedLocalRef<jstring> nameObj(env, env->NewStringUTF(deviceInfo.getDisplayName().c_str()));
if (!nameObj.get()) {
return NULL;
}
ScopedLocalRef<jstring> descriptorObj(env,
- env->NewStringUTF(deviceInfo.getIdentifier().descriptor.string()));
+ env->NewStringUTF(deviceInfo.getIdentifier().descriptor.c_str()));
if (!descriptorObj.get()) {
return NULL;
}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 189a4aa4fe28..517cf4df15a1 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -192,6 +192,7 @@ public class SettingsBackupTest {
Settings.Global.DEFAULT_DNS_SERVER,
Settings.Global.DEFAULT_INSTALL_LOCATION,
Settings.Global.DEFAULT_RESTRICT_BACKGROUND_DATA,
+ Settings.Global.DEFAULT_USER_ID_TO_BOOT_INTO,
Settings.Global.DESK_DOCK_SOUND,
Settings.Global.DESK_UNDOCK_SOUND,
Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT,
@@ -273,6 +274,7 @@ public class SettingsBackupTest {
Settings.Global.KEEP_PROFILE_IN_BACKGROUND,
Settings.Global.LANG_ID_UPDATE_CONTENT_URL,
Settings.Global.LANG_ID_UPDATE_METADATA_URL,
+ Settings.Global.LAST_ACTIVE_USER_ID,
Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST,
diff --git a/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
new file mode 100644
index 000000000000..297202bf4d71
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/LooperStatsTest.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Comparator;
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+@Presubmit
+public final class LooperStatsTest {
+ private HandlerThread mThreadFirst;
+ private HandlerThread mThreadSecond;
+ private Handler mHandlerFirst;
+ private Handler mHandlerSecond;
+ private Handler mHandlerAnonymous;
+
+ @Before
+ public void setUp() {
+ // The tests are all single-threaded. HandlerThreads are created to allow creating Handlers
+ // and to test Thread name collection.
+ mThreadFirst = new HandlerThread("TestThread1");
+ mThreadSecond = new HandlerThread("TestThread2");
+ mThreadFirst.start();
+ mThreadSecond.start();
+
+ mHandlerFirst = new TestHandlerFirst(mThreadFirst.getLooper());
+ mHandlerSecond = new TestHandlerSecond(mThreadSecond.getLooper());
+ mHandlerAnonymous = new Handler(mThreadFirst.getLooper()) {
+ /* To create an anonymous subclass. */
+ };
+ }
+
+ @After
+ public void tearDown() {
+ mThreadFirst.quit();
+ mThreadSecond.quit();
+ }
+
+ @Test
+ public void testSingleMessageDispatched() {
+ TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+
+ Object token = looperStats.messageDispatchStarting();
+ looperStats.tickRealtime(100);
+ looperStats.tickThreadTime(10);
+ looperStats.messageDispatched(token, mHandlerFirst.obtainMessage(1000));
+
+ List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+ assertThat(entries).hasSize(1);
+ LooperStats.ExportedEntry entry = entries.get(0);
+ assertThat(entry.threadName).isEqualTo("TestThread1");
+ assertThat(entry.handlerClassName).isEqualTo(
+ "com.android.internal.os.LooperStatsTest$TestHandlerFirst");
+ assertThat(entry.messageName).isEqualTo("0x3e8" /* 1000 in hex */);
+ assertThat(entry.messageCount).isEqualTo(1);
+ assertThat(entry.recordedMessageCount).isEqualTo(1);
+ assertThat(entry.exceptionCount).isEqualTo(0);
+ assertThat(entry.totalLatencyMicros).isEqualTo(100);
+ assertThat(entry.maxLatencyMicros).isEqualTo(100);
+ assertThat(entry.cpuUsageMicros).isEqualTo(10);
+ assertThat(entry.maxCpuUsageMicros).isEqualTo(10);
+ }
+
+ @Test
+ public void testThrewException() {
+ TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+
+ Object token = looperStats.messageDispatchStarting();
+ looperStats.tickRealtime(100);
+ looperStats.tickThreadTime(10);
+ looperStats.dispatchingThrewException(token, mHandlerFirst.obtainMessage(7),
+ new ArithmeticException());
+
+ List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+ assertThat(entries).hasSize(1);
+ LooperStats.ExportedEntry entry = entries.get(0);
+ assertThat(entry.threadName).isEqualTo("TestThread1");
+ assertThat(entry.handlerClassName).isEqualTo(
+ "com.android.internal.os.LooperStatsTest$TestHandlerFirst");
+ assertThat(entry.messageName).isEqualTo("0x7" /* 7 in hex */);
+ assertThat(entry.messageCount).isEqualTo(0);
+ assertThat(entry.recordedMessageCount).isEqualTo(0);
+ assertThat(entry.exceptionCount).isEqualTo(1);
+ assertThat(entry.totalLatencyMicros).isEqualTo(0);
+ assertThat(entry.maxLatencyMicros).isEqualTo(0);
+ assertThat(entry.cpuUsageMicros).isEqualTo(0);
+ assertThat(entry.maxCpuUsageMicros).isEqualTo(0);
+ }
+
+ @Test
+ public void testMultipleMessagesDispatched() {
+ TestableLooperStats looperStats = new TestableLooperStats(2, 100);
+
+ // Contributes to entry2.
+ Object token1 = looperStats.messageDispatchStarting();
+ looperStats.tickRealtime(100);
+ looperStats.tickThreadTime(10);
+ looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+
+ // Contributes to entry2.
+ Object token2 = looperStats.messageDispatchStarting();
+ looperStats.tickRealtime(50);
+ looperStats.tickThreadTime(20);
+ looperStats.messageDispatched(token2, mHandlerFirst.obtainMessage(1000));
+
+ // Contributes to entry3.
+ Object token3 = looperStats.messageDispatchStarting();
+ looperStats.tickRealtime(10);
+ looperStats.tickThreadTime(10);
+ looperStats.messageDispatched(token3, mHandlerSecond.obtainMessage().setCallback(() -> {
+ }));
+
+ // Contributes to entry1.
+ Object token4 = looperStats.messageDispatchStarting();
+ looperStats.tickRealtime(100);
+ looperStats.tickThreadTime(100);
+ looperStats.messageDispatched(token4, mHandlerAnonymous.obtainMessage(1));
+
+ List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+ assertThat(entries).hasSize(3);
+ entries.sort(Comparator.comparing(e -> e.handlerClassName));
+
+ // Captures data for token4 call.
+ LooperStats.ExportedEntry entry1 = entries.get(0);
+ assertThat(entry1.threadName).isEqualTo("TestThread1");
+ assertThat(entry1.handlerClassName).isEqualTo("com.android.internal.os.LooperStatsTest$1");
+ assertThat(entry1.messageName).isEqualTo("0x1" /* 1 in hex */);
+ assertThat(entry1.messageCount).isEqualTo(1);
+ assertThat(entry1.recordedMessageCount).isEqualTo(0);
+ assertThat(entry1.exceptionCount).isEqualTo(0);
+ assertThat(entry1.totalLatencyMicros).isEqualTo(0);
+ assertThat(entry1.maxLatencyMicros).isEqualTo(0);
+ assertThat(entry1.cpuUsageMicros).isEqualTo(0);
+ assertThat(entry1.maxCpuUsageMicros).isEqualTo(0);
+
+ // Captures data for token1 and token2 calls.
+ LooperStats.ExportedEntry entry2 = entries.get(1);
+ assertThat(entry2.threadName).isEqualTo("TestThread1");
+ assertThat(entry2.handlerClassName).isEqualTo(
+ "com.android.internal.os.LooperStatsTest$TestHandlerFirst");
+ assertThat(entry2.messageName).isEqualTo("0x3e8" /* 1000 in hex */);
+ assertThat(entry2.messageCount).isEqualTo(2);
+ assertThat(entry2.recordedMessageCount).isEqualTo(1);
+ assertThat(entry2.exceptionCount).isEqualTo(0);
+ assertThat(entry2.totalLatencyMicros).isEqualTo(100);
+ assertThat(entry2.maxLatencyMicros).isEqualTo(100);
+ assertThat(entry2.cpuUsageMicros).isEqualTo(10);
+ assertThat(entry2.maxCpuUsageMicros).isEqualTo(10);
+
+ // Captures data for token3 call.
+ LooperStats.ExportedEntry entry3 = entries.get(2);
+ assertThat(entry3.threadName).isEqualTo("TestThread2");
+ assertThat(entry3.handlerClassName).isEqualTo(
+ "com.android.internal.os.LooperStatsTest$TestHandlerSecond");
+ assertThat(entry3.messageName).startsWith(
+ "com.android.internal.os.-$$Lambda$LooperStatsTest$");
+ assertThat(entry3.messageCount).isEqualTo(1);
+ assertThat(entry3.recordedMessageCount).isEqualTo(1);
+ assertThat(entry3.exceptionCount).isEqualTo(0);
+ assertThat(entry3.totalLatencyMicros).isEqualTo(10);
+ assertThat(entry3.maxLatencyMicros).isEqualTo(10);
+ assertThat(entry3.cpuUsageMicros).isEqualTo(10);
+ assertThat(entry3.maxCpuUsageMicros).isEqualTo(10);
+ }
+
+ @Test
+ public void testMessagesOverSizeCap() {
+ TestableLooperStats looperStats = new TestableLooperStats(2, 1 /* sizeCap */);
+
+ Object token1 = looperStats.messageDispatchStarting();
+ looperStats.tickRealtime(100);
+ looperStats.tickThreadTime(10);
+ looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+
+ Object token2 = looperStats.messageDispatchStarting();
+ looperStats.tickRealtime(50);
+ looperStats.tickThreadTime(20);
+ looperStats.messageDispatched(token2, mHandlerFirst.obtainMessage(1001));
+
+ Object token3 = looperStats.messageDispatchStarting();
+ looperStats.tickRealtime(10);
+ looperStats.tickThreadTime(10);
+ looperStats.messageDispatched(token3, mHandlerFirst.obtainMessage(1002));
+
+ Object token4 = looperStats.messageDispatchStarting();
+ looperStats.tickRealtime(10);
+ looperStats.tickThreadTime(10);
+ looperStats.messageDispatched(token4, mHandlerSecond.obtainMessage(1003));
+
+ List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+ assertThat(entries).hasSize(2);
+ entries.sort(Comparator.comparing(e -> e.handlerClassName));
+
+ LooperStats.ExportedEntry entry1 = entries.get(0);
+ assertThat(entry1.threadName).isEqualTo("");
+ assertThat(entry1.handlerClassName).isEqualTo("");
+ assertThat(entry1.messageName).isEqualTo("OVERFLOW");
+ assertThat(entry1.messageCount).isEqualTo(3);
+ assertThat(entry1.recordedMessageCount).isEqualTo(1);
+ assertThat(entry1.exceptionCount).isEqualTo(0);
+ assertThat(entry1.totalLatencyMicros).isEqualTo(10);
+ assertThat(entry1.maxLatencyMicros).isEqualTo(10);
+ assertThat(entry1.cpuUsageMicros).isEqualTo(10);
+ assertThat(entry1.maxCpuUsageMicros).isEqualTo(10);
+
+ LooperStats.ExportedEntry entry2 = entries.get(1);
+ assertThat(entry2.threadName).isEqualTo("TestThread1");
+ assertThat(entry2.handlerClassName).isEqualTo(
+ "com.android.internal.os.LooperStatsTest$TestHandlerFirst");
+ }
+
+ @Test
+ public void testInvalidTokensCauseException() {
+ TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+ assertThrows(ClassCastException.class,
+ () -> looperStats.dispatchingThrewException(new Object(),
+ mHandlerFirst.obtainMessage(),
+ new ArithmeticException()));
+ assertThrows(ClassCastException.class,
+ () -> looperStats.messageDispatched(new Object(), mHandlerFirst.obtainMessage()));
+ assertThrows(ClassCastException.class,
+ () -> looperStats.messageDispatched(123, mHandlerFirst.obtainMessage()));
+ assertThrows(ClassCastException.class,
+ () -> looperStats.messageDispatched(mHandlerFirst.obtainMessage(),
+ mHandlerFirst.obtainMessage()));
+
+ assertThat(looperStats.getEntries()).hasSize(0);
+ }
+
+ @Test
+ public void testTracksMultipleHandlerInstancesIfSameClass() {
+ TestableLooperStats looperStats = new TestableLooperStats(1, 100);
+ Handler handlerFirstAnother = new TestHandlerFirst(mHandlerFirst.getLooper());
+
+ Object token1 = looperStats.messageDispatchStarting();
+ looperStats.messageDispatched(token1, mHandlerFirst.obtainMessage(1000));
+
+ Object token2 = looperStats.messageDispatchStarting();
+ looperStats.messageDispatched(token2, handlerFirstAnother.obtainMessage(1000));
+
+ assertThat(looperStats.getEntries()).hasSize(1);
+ assertThat(looperStats.getEntries().get(0).messageCount).isEqualTo(2);
+ }
+
+ private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) {
+ try {
+ r.run();
+ Assert.fail("Expected " + exceptionClass + " to be thrown.");
+ } catch (Exception exception) {
+ assertThat(exception).isInstanceOf(exceptionClass);
+ }
+ }
+
+ private static final class TestableLooperStats extends LooperStats {
+ private static final long INITIAL_MICROS = 10001000123L;
+ private int mCount;
+ private long mRealtimeMicros;
+ private long mThreadTimeMicros;
+ private int mSamplingInterval;
+
+ TestableLooperStats(int samplingInterval, int sizeCap) {
+ super(samplingInterval, sizeCap);
+ this.mSamplingInterval = samplingInterval;
+ }
+
+ void tickRealtime(long micros) {
+ mRealtimeMicros += micros;
+ }
+
+ void tickThreadTime(long micros) {
+ mThreadTimeMicros += micros;
+ }
+
+ @Override
+ protected long getElapsedRealtimeMicro() {
+ return INITIAL_MICROS + mRealtimeMicros;
+ }
+
+ @Override
+ protected long getThreadTimeMicro() {
+ return INITIAL_MICROS + mThreadTimeMicros;
+ }
+
+ @Override
+ protected boolean shouldCollectDetailedData() {
+ return mCount++ % mSamplingInterval == 0;
+ }
+ }
+
+ private static final class TestHandlerFirst extends Handler {
+ TestHandlerFirst(Looper looper) {
+ super(looper);
+ }
+ }
+
+ private static final class TestHandlerSecond extends Handler {
+ TestHandlerSecond(Looper looper) {
+ super(looper);
+ }
+ }
+}
diff --git a/graphics/java/android/graphics/Insets.java b/graphics/java/android/graphics/Insets.java
index 5a78530852c7..c3449dd4fb47 100644
--- a/graphics/java/android/graphics/Insets.java
+++ b/graphics/java/android/graphics/Insets.java
@@ -16,6 +16,9 @@
package android.graphics;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
/**
* An Insets instance holds four integer offsets which describe changes to the four
* edges of a Rectangle. By convention, positive values move edges towards the
@@ -24,7 +27,7 @@ package android.graphics;
* Insets are immutable so may be treated as values.
*
*/
-public class Insets {
+public final class Insets {
public static final Insets NONE = new Insets(0, 0, 0, 0);
public final int left;
@@ -51,7 +54,7 @@ public class Insets {
*
* @return Insets instance with the appropriate values
*/
- public static Insets of(int left, int top, int right, int bottom) {
+ public static @NonNull Insets of(int left, int top, int right, int bottom) {
if (left == 0 && top == 0 && right == 0 && bottom == 0) {
return NONE;
}
@@ -65,7 +68,7 @@ public class Insets {
*
* @return an Insets instance with the appropriate values
*/
- public static Insets of(Rect r) {
+ public static @NonNull Insets of(@Nullable Rect r) {
return (r == null) ? NONE : of(r.left, r.top, r.right, r.bottom);
}
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 67682a06cb6a..c5a6ec590d30 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -36,9 +36,8 @@ cc_library_shared {
cflags: [
"-Wall",
+ "-Wextra",
"-Werror",
- "-Wunused",
- "-Wunreachable-code",
],
}
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 4794f3da824c..eb3469e0b3f0 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -28,7 +28,6 @@
#include <utils/BitSet.h>
#include <utils/RefBase.h>
#include <utils/Looper.h>
-#include <utils/String8.h>
#include <gui/DisplayEventReceiver.h>
namespace android {
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index 173cd507d943..eb2bc98ec9e9 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -23,14 +23,10 @@
#include <utils/String8.h>
#include <gui/Surface.h>
-// ToDo: Fix code to be warning free
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <SkBitmap.h>
#include <SkCanvas.h>
#include <SkColor.h>
#include <SkPaint.h>
-#pragma GCC diagnostic pop
#include <android/native_window.h>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index 663b1f5e4789..240a19279739 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -675,6 +675,7 @@ public class ApplicationsState {
if (!mResumed) {
mResumed = true;
mSessionsChanged = true;
+ doPauseLocked();
doResumeIfNeededLocked();
}
}
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 19492a08e7a2..11bd392b7d52 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -79,13 +79,6 @@
<!-- Show camera affordance on Keyguard -->
<bool name="config_keyguardShowCameraAffordance">false</bool>
- <!-- Whether we should use SRC drawing mode when drawing the scrim behind. If this flag is set,
- we change the canvas opacity so libhwui doesn't call glClear on our surface, and then we
- draw the scrim with SRC to overwrite the whole buffer, which saves us a layer of overdraw.
- However, SRC performs poorly on some devices, where it is more efficient to
- glClear + SRC_OVER, in which case this flag should be disabled. -->
- <bool name="config_status_bar_scrim_behind_use_src">true</bool>
-
<!-- The length of the vibration when the notification pops open. -->
<integer name="one_finger_pop_duration_ms">10</integer>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index d051f07e44a8..26eadb5bfa2d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -361,7 +361,7 @@
<dimen name="qs_quick_layout_width">-1px</dimen>
<dimen name="qs_quick_tile_padding">12dp</dimen>
<dimen name="qs_header_gear_translation">16dp</dimen>
- <dimen name="qs_header_tile_margin_horizontal">0dp</dimen>
+ <dimen name="qs_header_tile_margin_horizontal">4dp</dimen>
<dimen name="qs_page_indicator_width">16dp</dimen>
<dimen name="qs_page_indicator_height">8dp</dimen>
<dimen name="qs_tile_icon_size">24dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
index eaa4c6de0202..3bc434280c51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
@@ -53,11 +53,8 @@ public class ScrimView extends View implements ConfigurationController.Configura
private static final String TAG = "ScrimView";
private final ColorExtractor.GradientColors mColors;
private int mDensity;
- private boolean mDrawAsSrc;
private float mViewAlpha = 1.0f;
private ValueAnimator mAlphaAnimator;
- private Rect mExcludedRect = new Rect();
- private boolean mHasExcludedArea;
private Drawable mDrawable;
private PorterDuffColorFilter mColorFilter;
private int mTintColor;
@@ -137,59 +134,8 @@ public class ScrimView extends View implements ConfigurationController.Configura
@Override
protected void onDraw(Canvas canvas) {
- if (mDrawAsSrc || mDrawable.getAlpha() > 0) {
- if (!mHasExcludedArea) {
- mDrawable.draw(canvas);
- } else {
- if (mExcludedRect.top > 0) {
- canvas.save();
- canvas.clipRect(0, 0, getWidth(), mExcludedRect.top);
- mDrawable.draw(canvas);
- canvas.restore();
- }
- if (mExcludedRect.left > 0) {
- canvas.save();
- canvas.clipRect(0, mExcludedRect.top, mExcludedRect.left,
- mExcludedRect.bottom);
- mDrawable.draw(canvas);
- canvas.restore();
- }
- if (mExcludedRect.right < getWidth()) {
- canvas.save();
- canvas.clipRect(mExcludedRect.right, mExcludedRect.top, getWidth(),
- mExcludedRect.bottom);
- mDrawable.draw(canvas);
- canvas.restore();
- }
- if (mExcludedRect.bottom < getHeight()) {
- canvas.save();
- canvas.clipRect(0, mExcludedRect.bottom, getWidth(), getHeight());
- mDrawable.draw(canvas);
- canvas.restore();
- }
- // We also need to draw the rounded corners of the background
- canvas.save();
- canvas.clipRect(mExcludedRect.left, mExcludedRect.top,
- mExcludedRect.left + mCornerRadius, mExcludedRect.top + mCornerRadius);
- mDrawable.draw(canvas);
- canvas.restore();
- canvas.save();
- canvas.clipRect(mExcludedRect.right - mCornerRadius, mExcludedRect.top,
- mExcludedRect.right, mExcludedRect.top + mCornerRadius);
- mDrawable.draw(canvas);
- canvas.restore();
- canvas.save();
- canvas.clipRect(mExcludedRect.left, mExcludedRect.bottom - mCornerRadius,
- mExcludedRect.left + mCornerRadius, mExcludedRect.bottom);
- mDrawable.draw(canvas);
- canvas.restore();
- canvas.save();
- canvas.clipRect(mExcludedRect.right - mCornerRadius,
- mExcludedRect.bottom - mCornerRadius,
- mExcludedRect.right, mExcludedRect.bottom);
- mDrawable.draw(canvas);
- canvas.restore();
- }
+ if (mDrawable.getAlpha() > 0) {
+ mDrawable.draw(canvas);
}
}
@@ -198,7 +144,6 @@ public class ScrimView extends View implements ConfigurationController.Configura
mDrawable.setCallback(this);
mDrawable.setBounds(getLeft(), getTop(), getRight(), getBottom());
mDrawable.setAlpha((int) (255 * mViewAlpha));
- setDrawAsSrc(mDrawAsSrc);
updateScreenSize();
invalidate();
}
@@ -211,12 +156,6 @@ public class ScrimView extends View implements ConfigurationController.Configura
}
}
- public void setDrawAsSrc(boolean asSrc) {
- mDrawAsSrc = asSrc;
- PorterDuff.Mode mode = asSrc ? PorterDuff.Mode.SRC : PorterDuff.Mode.SRC_OVER;
- mDrawable.setXfermode(new PorterDuffXfermode(mode));
- }
-
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
@@ -328,22 +267,6 @@ public class ScrimView extends View implements ConfigurationController.Configura
return mViewAlpha;
}
- public void setExcludedArea(Rect area) {
- if (area == null) {
- mHasExcludedArea = false;
- invalidate();
- return;
- }
-
- int left = Math.max(area.left, 0);
- int top = Math.max(area.top, 0);
- int right = Math.min(area.right, getWidth());
- int bottom = Math.min(area.bottom, getHeight());
- mExcludedRect.set(left, top, right, bottom);
- mHasExcludedArea = left < right && top < bottom;
- invalidate();
- }
-
public void setChangeRunnable(Runnable changeRunnable) {
mChangeRunnable = changeRunnable;
}
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 4f554b656b26..1883aa7e7845 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
@@ -394,9 +394,6 @@ public class NotificationStackScrollLayout extends ViewGroup
};
private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
private boolean mPulsing;
- private boolean mDrawBackgroundAsSrc;
- private boolean mFadingOut;
- private boolean mParentNotFullyVisible;
private boolean mGroupExpandedForMeasure;
private boolean mScrollable;
private View mForcedScroll;
@@ -789,21 +786,6 @@ public class NotificationStackScrollLayout extends ViewGroup
R.dimen.heads_up_status_bar_padding);
}
- public void setDrawBackgroundAsSrc(boolean asSrc) {
- mDrawBackgroundAsSrc = asSrc;
- updateSrcDrawing();
- }
-
- private void updateSrcDrawing() {
- if (!mShouldDrawNotificationBackground) {
- return;
- }
-
- mBackgroundPaint.setXfermode(mDrawBackgroundAsSrc && !mFadingOut && !mParentNotFullyVisible
- ? mSrcMode : null);
- invalidate();
- }
-
private void notifyHeightChangeListener(ExpandableView view) {
notifyHeightChangeListener(view, false /* needsAnimation */);
}
@@ -1128,7 +1110,6 @@ public class NotificationStackScrollLayout extends ViewGroup
&& !mHeadsUpAnimatingAway;
if (mIsClipped != clipped) {
mIsClipped = clipped;
- updateFadingState();
}
if (animatingClipping) {
@@ -2447,7 +2428,7 @@ public class NotificationStackScrollLayout extends ViewGroup
startBackgroundAnimation();
} else {
mCurrentBounds.set(mBackgroundBounds);
- applyCurrentBackgroundBounds();
+ invalidate();
}
} else {
abortBackgroundAnimators();
@@ -2575,25 +2556,11 @@ public class NotificationStackScrollLayout extends ViewGroup
private void setBackgroundTop(int top) {
mCurrentBounds.top = top;
- applyCurrentBackgroundBounds();
+ invalidate();
}
public void setBackgroundBottom(int bottom) {
mCurrentBounds.bottom = bottom;
- applyCurrentBackgroundBounds();
- }
-
- private void applyCurrentBackgroundBounds() {
- // If the background of the notification is not being drawn, then there is no need to
- // exclude an area in the scrim. Rather, the scrim's color should serve as the background.
- if (!mShouldDrawNotificationBackground) {
- return;
- }
-
- final boolean awake = mInterpolatedDarkAmount != 0 || mAmbientState.isDark();
- mScrimController.setExcludedBackgroundArea(
- mFadingOut || mParentNotFullyVisible || awake || mIsClipped ? null
- : mCurrentBounds);
invalidate();
}
@@ -4176,7 +4143,6 @@ public class NotificationStackScrollLayout extends ViewGroup
updateBackground();
}
requestChildrenUpdate();
- applyCurrentBackgroundBounds();
updateWillNotDraw();
notifyHeightChangeListener(mShelf);
}
@@ -4650,35 +4616,6 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
- public void setFadingOut(boolean fadingOut) {
- if (fadingOut != mFadingOut) {
- mFadingOut = fadingOut;
- updateFadingState();
- }
- }
-
- public void setParentNotFullyVisible(boolean parentNotFullyVisible) {
- if (mScrimController == null) {
- // we're not set up yet.
- return;
- }
- if (parentNotFullyVisible != mParentNotFullyVisible) {
- mParentNotFullyVisible = parentNotFullyVisible;
- updateFadingState();
- }
- }
-
- private void updateFadingState() {
- applyCurrentBackgroundBounds();
- updateSrcDrawing();
- }
-
- @Override
- public void setAlpha(@FloatRange(from = 0.0, to = 1.0) float alpha) {
- super.setAlpha(alpha);
- setFadingOut(alpha != 1.0f);
- }
-
public void setQsExpanded(boolean qsExpanded) {
mQsExpanded = qsExpanded;
updateAlgorithmLayoutMinHeight();
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 33ddfde845a5..e5e5d4038c37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -2668,32 +2668,6 @@ public class NotificationPanelView extends PanelView implements
setLaunchingAffordance(false);
}
- @Override
- public void setAlpha(float alpha) {
- super.setAlpha(alpha);
- updateFullyVisibleState(false /* forceNotFullyVisible */);
- }
-
- /**
- * Must be called before starting a ViewPropertyAnimator alpha animation because those
- * do NOT call setAlpha and therefore don't properly update the fullyVisibleState.
- */
- public void notifyStartFading() {
- updateFullyVisibleState(true /* forceNotFullyVisible */);
- }
-
- @Override
- public void setVisibility(int visibility) {
- super.setVisibility(visibility);
- updateFullyVisibleState(false /* forceNotFullyVisible */);
- }
-
- private void updateFullyVisibleState(boolean forceNotFullyVisible) {
- mNotificationStackScroller.setParentNotFullyVisible(forceNotFullyVisible
- || getAlpha() != 1.0f
- || getVisibility() != VISIBLE);
- }
-
/**
* Set whether we are currently launching an affordance. This is currently only set when
* launched via a camera gesture.
@@ -2992,10 +2966,6 @@ public class NotificationPanelView extends PanelView implements
mNotificationStackScroller.setActivatedChild(o);
}
- public void setParentNotFullyVisible(boolean parent) {
- mNotificationStackScroller.setParentNotFullyVisible(parent);
- }
-
public void runAfterAnimationFinished(Runnable r) {
mNotificationStackScroller.runAfterAnimationFinished(r);
}
@@ -3020,8 +2990,4 @@ public class NotificationPanelView extends PanelView implements
mNotificationStackScroller.setScrimController(scrimController);
updateShowEmptyShadeView();
}
-
- public void setDrawBackgroundAsSrc(boolean asSrc) {
- mNotificationStackScroller.setDrawBackgroundAsSrc(asSrc);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 0c361ce26e34..e3a7b75554d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -685,10 +685,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
return scrim.getTag(TAG_KEY_ANIM) != null;
}
- public void setDrawBehindAsSrc(boolean asSrc) {
- mScrimBehind.setDrawAsSrc(asSrc);
- }
-
@VisibleForTesting
void setOnAnimationFinished(Runnable onAnimationFinished) {
mOnAnimationFinished = onAnimationFinished;
@@ -800,10 +796,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
return Handler.getMain();
}
- public void setExcludedBackgroundArea(Rect area) {
- mScrimBehind.setExcludedArea(area);
- }
-
public int getBackgroundColor() {
int color = mLockColors.getMainColor();
return Color.argb((int) (mScrimBehind.getViewAlpha() * Color.alpha(color)),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 9beaa10d6bd0..7ec4db21b694 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -328,14 +328,6 @@ public class StatusBar extends SystemUI implements DemoMode,
/** If true, the lockscreen will show a distinct wallpaper */
private static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true;
- /**
- * Never let the alpha become zero for surfaces that draw with SRC - otherwise the RenderNode
- * won't draw anything and uninitialized memory will show through
- * if mScrimSrcModeEnabled. Note that 0.001 is rounded down to 0 in
- * libhwui.
- */
- private static final float SRC_MIN_ALPHA = 0.002f;
-
static {
boolean onlyCoreApps;
try {
@@ -485,7 +477,6 @@ public class StatusBar extends SystemUI implements DemoMode,
protected boolean mDozing;
private boolean mDozingRequested;
- protected boolean mScrimSrcModeEnabled;
protected BackDropView mBackdrop;
protected ImageView mBackdropFront, mBackdropBack;
@@ -652,7 +643,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mVibrateOnOpening = mContext.getResources().getBoolean(
R.bool.config_vibrateOnIconAnimation);
mVibratorHelper = Dependency.get(VibratorHelper.class);
- mScrimSrcModeEnabled = res.getBoolean(R.bool.config_status_bar_scrim_behind_use_src);
DateTimeView.setReceiverHandler(Dependency.get(Dependency.TIME_TICK_HANDLER));
putComponent(StatusBar.class, this);
@@ -948,15 +938,6 @@ public class StatusBar extends SystemUI implements DemoMode,
}
}, DozeParameters.getInstance(mContext),
mContext.getSystemService(AlarmManager.class));
- if (mScrimSrcModeEnabled) {
- Runnable runnable = () -> {
- boolean asSrc = mBackdrop.getVisibility() != View.VISIBLE;
- mScrimController.setDrawBehindAsSrc(asSrc);
- mNotificationPanel.setDrawBackgroundAsSrc(asSrc);
- };
- mBackdrop.setOnVisibilityChangedRunnable(runnable);
- runnable.run();
- }
mNotificationPanel.initDependencies(this, mGroupManager, mNotificationShelf,
mHeadsUpManager, mNotificationIconAreaController, mScrimController);
mDozeScrimController = new DozeScrimController(mScrimController, context,
@@ -1483,7 +1464,7 @@ public class StatusBar extends SystemUI implements DemoMode,
if (mBackdrop.getVisibility() != View.VISIBLE) {
mBackdrop.setVisibility(View.VISIBLE);
if (allowEnterAnimation) {
- mBackdrop.setAlpha(SRC_MIN_ALPHA);
+ mBackdrop.setAlpha(0);
mBackdrop.animate().alpha(1f);
} else {
mBackdrop.animate().cancel();
@@ -1501,9 +1482,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mBackdropBack.getDrawable().getConstantState()
.newDrawable(mBackdropFront.getResources()).mutate();
mBackdropFront.setImageDrawable(drawable);
- if (mScrimSrcModeEnabled) {
- mBackdropFront.getDrawable().mutate().setXfermode(mSrcOverXferMode);
- }
mBackdropFront.setAlpha(1f);
mBackdropFront.setVisibility(View.VISIBLE);
} else {
@@ -1518,9 +1496,6 @@ public class StatusBar extends SystemUI implements DemoMode,
} else {
mBackdropBack.setImageDrawable(artworkDrawable);
}
- if (mScrimSrcModeEnabled) {
- mBackdropBack.getDrawable().mutate().setXfermode(mSrcXferMode);
- }
if (mBackdropFront.getVisibility() == View.VISIBLE) {
if (DEBUG_MEDIA) {
@@ -1553,7 +1528,7 @@ public class StatusBar extends SystemUI implements DemoMode,
} else {
mStatusBarWindowController.setBackdropShowing(false);
mBackdrop.animate()
- .alpha(SRC_MIN_ALPHA)
+ .alpha(0)
.setInterpolator(Interpolators.ACCELERATE_DECELERATE)
.setDuration(300)
.setStartDelay(0)
@@ -1765,10 +1740,6 @@ public class StatusBar extends SystemUI implements DemoMode,
return mMediaManager.getMediaNotificationKey();
}
- public boolean isScrimSrcModeEnabled() {
- return mScrimSrcModeEnabled;
- }
-
/**
* To be called when there's a state change in StatusBarKeyguardViewManager.
*/
@@ -3410,7 +3381,6 @@ public class StatusBar extends SystemUI implements DemoMode,
updateScrimController();
updateMediaMetaData(false, true);
mNotificationPanel.setAlpha(1);
- mNotificationPanel.setParentNotFullyVisible(true);
mNotificationPanel.animate()
.alpha(0)
.setStartDelay(FADE_KEYGUARD_START_DELAY)
@@ -3432,7 +3402,6 @@ public class StatusBar extends SystemUI implements DemoMode,
* fading.
*/
public void fadeKeyguardWhilePulsing() {
- mNotificationPanel.notifyStartFading();
mNotificationPanel.animate()
.alpha(0f)
.setStartDelay(0)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 98f1a3693e06..45b32c7abae0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -227,20 +227,7 @@ public class StatusBarWindowView extends FrameLayout {
@Override
protected void onAttachedToWindow () {
super.onAttachedToWindow();
-
- // We need to ensure that our window doesn't suffer from overdraw which would normally
- // occur if our window is translucent. Since we are drawing the whole window anyway with
- // the scrim, we don't need the window to be cleared in the beginning.
- if (mService.isScrimSrcModeEnabled()) {
- IBinder windowToken = getWindowToken();
- WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
- lp.token = windowToken;
- setLayoutParams(lp);
- WindowManagerGlobal.getInstance().changeCanvasOpacity(windowToken, true);
- setWillNotDraw(false);
- } else {
- setWillNotDraw(!DEBUG);
- }
+ setWillNotDraw(!DEBUG);
}
@Override
@@ -394,26 +381,6 @@ public class StatusBarWindowView extends FrameLayout {
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
- if (mService.isScrimSrcModeEnabled()) {
- // We need to ensure that our window is always drawn fully even when we have paddings,
- // since we simulate it to be opaque.
- int paddedBottom = getHeight() - getPaddingBottom();
- int paddedRight = getWidth() - getPaddingRight();
- if (getPaddingTop() != 0) {
- canvas.drawRect(0, 0, getWidth(), getPaddingTop(), mTransparentSrcPaint);
- }
- if (getPaddingBottom() != 0) {
- canvas.drawRect(0, paddedBottom, getWidth(), getHeight(), mTransparentSrcPaint);
- }
- if (getPaddingLeft() != 0) {
- canvas.drawRect(0, getPaddingTop(), getPaddingLeft(), paddedBottom,
- mTransparentSrcPaint);
- }
- if (getPaddingRight() != 0) {
- canvas.drawRect(paddedRight, getPaddingTop(), getWidth(), paddedBottom,
- mTransparentSrcPaint);
- }
- }
if (DEBUG) {
Paint pt = new Paint();
pt.setColor(0x80FFFF00);
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
index 238407a9a6f1..a46f018af816 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java
@@ -16,17 +16,13 @@
package com.android.systemui.usb;
-import android.annotation.NonNull;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
-import android.content.res.XmlResourceParser;
import android.hardware.usb.IUsbManager;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbDevice;
@@ -45,13 +41,8 @@ import android.widget.TextView;
import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
-import com.android.internal.util.XmlUtils;
-import android.hardware.usb.AccessoryFilter;
-import android.hardware.usb.DeviceFilter;
import com.android.systemui.R;
-import org.xmlpull.v1.XmlPullParser;
-
public class UsbPermissionActivity extends AlertActivity
implements DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener {
@@ -71,12 +62,13 @@ public class UsbPermissionActivity extends AlertActivity
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- Intent intent = getIntent();
+ Intent intent = getIntent();
mDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
mPendingIntent = (PendingIntent)intent.getParcelableExtra(Intent.EXTRA_INTENT);
mUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
- mPackageName = intent.getStringExtra("package");
+ mPackageName = intent.getStringExtra(UsbManager.EXTRA_PACKAGE);
+ boolean canBeDefault = intent.getBooleanExtra(UsbManager.EXTRA_CAN_BE_DEFAULT, false);
PackageManager packageManager = getPackageManager();
ApplicationInfo aInfo;
@@ -105,121 +97,27 @@ public class UsbPermissionActivity extends AlertActivity
ap.mPositiveButtonListener = this;
ap.mNegativeButtonListener = this;
- try {
- PackageInfo packageInfo = packageManager.getPackageInfo(mPackageName,
- PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA);
-
- if ((mDevice != null && canBeDefault(mDevice, packageInfo))
- || (mAccessory != null && canBeDefault(mAccessory, packageInfo))) {
- // add "open when" checkbox
- LayoutInflater inflater = (LayoutInflater) getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
- mAlwaysUse = (CheckBox) ap.mView.findViewById(com.android.internal.R.id.alwaysUse);
- if (mDevice == null) {
- mAlwaysUse.setText(getString(R.string.always_use_accessory, appName,
- mAccessory.getDescription()));
- } else {
- mAlwaysUse.setText(getString(R.string.always_use_device, appName,
- mDevice.getProductName()));
- }
- mAlwaysUse.setOnCheckedChangeListener(this);
-
- mClearDefaultHint = (TextView)ap.mView.findViewById(
- com.android.internal.R.id.clearDefaultHint);
- mClearDefaultHint.setVisibility(View.GONE);
+ if (canBeDefault && (mDevice != null || mAccessory != null)) {
+ // add "open when" checkbox
+ LayoutInflater inflater = (LayoutInflater) getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
+ mAlwaysUse = (CheckBox) ap.mView.findViewById(com.android.internal.R.id.alwaysUse);
+ if (mDevice == null) {
+ mAlwaysUse.setText(getString(R.string.always_use_accessory, appName,
+ mAccessory.getDescription()));
+ } else {
+ mAlwaysUse.setText(getString(R.string.always_use_device, appName,
+ mDevice.getProductName()));
}
- } catch (PackageManager.NameNotFoundException e) {
- // ignore
- }
-
- setupAlert();
-
- }
-
- /**
- * Can the app be the default for the USB device. I.e. can the app be launched by default if
- * the device is plugged in.
- *
- * @param device The device the app would be default for
- * @param packageInfo The package info of the app
- *
- * @return {@code true} iff the app can be default
- */
- private boolean canBeDefault(@NonNull UsbDevice device, @NonNull PackageInfo packageInfo) {
- ActivityInfo[] activities = packageInfo.activities;
- if (activities != null) {
- int numActivities = activities.length;
- for (int i = 0; i < numActivities; i++) {
- ActivityInfo activityInfo = activities[i];
+ mAlwaysUse.setOnCheckedChangeListener(this);
- try (XmlResourceParser parser = activityInfo.loadXmlMetaData(getPackageManager(),
- UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
- if (parser == null) {
- continue;
- }
-
- XmlUtils.nextElement(parser);
- while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
- if ("usb-device".equals(parser.getName())) {
- DeviceFilter filter = DeviceFilter.read(parser);
- if (filter.matches(device)) {
- return true;
- }
- }
-
- XmlUtils.nextElement(parser);
- }
- } catch (Exception e) {
- Log.w(TAG, "Unable to load component info " + activityInfo.toString(), e);
- }
- }
- }
-
- return false;
- }
-
- /**
- * Can the app be the default for the USB accessory. I.e. can the app be launched by default if
- * the accessory is plugged in.
- *
- * @param accessory The accessory the app would be default for
- * @param packageInfo The package info of the app
- *
- * @return {@code true} iff the app can be default
- */
- private boolean canBeDefault(@NonNull UsbAccessory accessory,
- @NonNull PackageInfo packageInfo) {
- ActivityInfo[] activities = packageInfo.activities;
- if (activities != null) {
- int numActivities = activities.length;
- for (int i = 0; i < numActivities; i++) {
- ActivityInfo activityInfo = activities[i];
-
- try (XmlResourceParser parser = activityInfo.loadXmlMetaData(getPackageManager(),
- UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) {
- if (parser == null) {
- continue;
- }
-
- XmlUtils.nextElement(parser);
- while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
- if ("usb-accessory".equals(parser.getName())) {
- AccessoryFilter filter = AccessoryFilter.read(parser);
- if (filter.matches(accessory)) {
- return true;
- }
- }
-
- XmlUtils.nextElement(parser);
- }
- } catch (Exception e) {
- Log.w(TAG, "Unable to load component info " + activityInfo.toString(), e);
- }
- }
+ mClearDefaultHint = (TextView)ap.mView.findViewById(
+ com.android.internal.R.id.clearDefaultHint);
+ mClearDefaultHint.setVisibility(View.GONE);
}
- return false;
+ setupAlert();
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ScrimViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ScrimViewTest.java
index 42dad114b6b6..c2611e410fad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/ScrimViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/ScrimViewTest.java
@@ -92,15 +92,6 @@ public class ScrimViewTest extends LeakCheckedTest {
}
@Test
- public void testOnDraw_ExcludeRectDrawable() {
- mView.setExcludedArea(new Rect(10, 10, 20, 20));
- Canvas canvas = mock(Canvas.class);
- mView.onDraw(canvas);
- // One time for each rect side
- verify(canvas, times(8)).clipRect(anyInt(), anyInt(), anyInt(), anyInt());
- }
-
- @Test
public void setTint_set() {
int tint = Color.BLUE;
mView.setTint(tint);
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 4d3468e21e75..44dddd14d83d 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -4386,12 +4386,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private static final class LocalServiceImpl extends InputMethodManagerInternal {
@NonNull
private final InputMethodManagerService mService;
- @NonNull
- private final Handler mHandler;
LocalServiceImpl(@NonNull InputMethodManagerService service) {
mService = service;
- mHandler = service.mHandler;
}
@Override
@@ -4411,19 +4408,19 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@Override
public void setInteractive(boolean interactive) {
// Do everything in handler so as not to block the caller.
- mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_INTERACTIVE,
- interactive ? 1 : 0, 0));
+ mService.mHandler.obtainMessage(MSG_SET_INTERACTIVE, interactive ? 1 : 0, 0)
+ .sendToTarget();
}
@Override
public void hideCurrentInputMethod() {
- mHandler.removeMessages(MSG_HIDE_CURRENT_INPUT_METHOD);
- mHandler.sendEmptyMessage(MSG_HIDE_CURRENT_INPUT_METHOD);
+ mService.mHandler.removeMessages(MSG_HIDE_CURRENT_INPUT_METHOD);
+ mService.mHandler.sendEmptyMessage(MSG_HIDE_CURRENT_INPUT_METHOD);
}
@Override
public void startVrInputMethodNoCheck(@Nullable ComponentName componentName) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_START_VR_INPUT, componentName));
+ mService.mHandler.obtainMessage(MSG_START_VR_INPUT, componentName).sendToTarget();
}
}
diff --git a/services/core/java/com/android/server/LooperStatsService.java b/services/core/java/com/android/server/LooperStatsService.java
new file mode 100644
index 000000000000..237e169a989f
--- /dev/null
+++ b/services/core/java/com/android/server/LooperStatsService.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.content.Context;
+import android.os.Binder;
+import android.os.Looper;
+import android.os.ResultReceiver;
+import android.os.ShellCallback;
+import android.os.ShellCommand;
+
+import com.android.internal.os.LooperStats;
+import com.android.internal.util.DumpUtils;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @hide Only for use within the system server.
+ */
+public class LooperStatsService extends Binder {
+ private static final String TAG = "LooperStatsService";
+ private static final String LOOPER_STATS_SERVICE_NAME = "looper_stats";
+
+ private final Context mContext;
+ private final LooperStats mStats;
+ private boolean mEnabled = false;
+
+ private LooperStatsService(Context context, LooperStats stats) {
+ this.mContext = context;
+ this.mStats = stats;
+ }
+
+ @Override
+ public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
+ (new LooperShellCommand()).exec(this, in, out, err, args, callback, resultReceiver);
+ }
+
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+ List<LooperStats.ExportedEntry> entries = mStats.getEntries();
+ entries.sort(Comparator
+ .comparing((LooperStats.ExportedEntry entry) -> entry.threadName)
+ .thenComparing(entry -> entry.handlerClassName)
+ .thenComparing(entry -> entry.messageName));
+ String header = String.join(",", Arrays.asList(
+ "thread_name",
+ "handler_class",
+ "message_name",
+ "message_count",
+ "recorded_message_count",
+ "total_latency_micros",
+ "max_latency_micros",
+ "total_cpu_micros",
+ "max_cpu_micros",
+ "exception_count"));
+ pw.println(header);
+ for (LooperStats.ExportedEntry entry : entries) {
+ pw.printf("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", entry.threadName, entry.handlerClassName,
+ entry.messageName, entry.messageCount, entry.recordedMessageCount,
+ entry.totalLatencyMicros, entry.maxLatencyMicros, entry.cpuUsageMicros,
+ entry.maxCpuUsageMicros, entry.exceptionCount);
+ }
+ }
+
+ private void setEnabled(boolean enabled) {
+ if (mEnabled != enabled) {
+ mEnabled = enabled;
+ mStats.reset();
+ Looper.setObserver(enabled ? mStats : null);
+ }
+ }
+
+ /**
+ * Manages the lifecycle of LooperStatsService within System Server.
+ */
+ public static class Lifecycle extends SystemService {
+ public Lifecycle(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ LooperStats stats = new LooperStats();
+ publishLocalService(LooperStats.class, stats);
+ // TODO: publish LooperStatsService as a binder service when the SE Policy is changed.
+ }
+ }
+
+ private class LooperShellCommand extends ShellCommand {
+ @Override
+ public int onCommand(String cmd) {
+ if ("enable".equals(cmd)) {
+ setEnabled(true);
+ return 0;
+ } else if ("disable".equals(cmd)) {
+ setEnabled(false);
+ return 0;
+ } else if ("reset".equals(cmd)) {
+ mStats.reset();
+ return 0;
+ } else {
+ return handleDefaultCommands(cmd);
+ }
+ }
+
+ @Override
+ public void onHelp() {
+ final PrintWriter pw = getOutPrintWriter();
+ pw.println(LOOPER_STATS_SERVICE_NAME + " commands:");
+ pw.println(" enable: Enable collecting stats");
+ pw.println(" disable: Disable collecting stats");
+ pw.println(" reset: Reset stats");
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 9df9ba600f2a..2750dc13b408 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -16,6 +16,9 @@
package com.android.server.input;
+import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
+import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
+
import android.annotation.NonNull;
import android.os.LocaleList;
import android.os.ShellCallback;
@@ -292,11 +295,6 @@ public class InputManagerService extends IInputManager.Stub
/** Switch code: Camera lens cover. When set the lens is covered. */
public static final int SW_CAMERA_LENS_COVER = 0x09;
- // Viewport constants defined in InputReader.h.
- public static final int VIEWPORT_DEFAULT = 1;
- public static final int VIEWPORT_EXTERNAL = 2;
- public static final int VIEWPORT_VIRTUAL = 3;
-
public static final int SW_LID_BIT = 1 << SW_LID;
public static final int SW_TABLET_MODE_BIT = 1 << SW_TABLET_MODE;
public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
@@ -362,7 +360,7 @@ public class InputManagerService extends IInputManager.Stub
updateAccessibilityLargePointerFromSettings();
}
- // TODO(BT) Pass in paramter for bluetooth system
+ // TODO(BT) Pass in parameter for bluetooth system
public void systemRunning() {
if (DEBUG) {
Slog.d(TAG, "System ready.");
@@ -417,7 +415,7 @@ public class InputManagerService extends IInputManager.Stub
DisplayViewport externalTouchViewport,
List<DisplayViewport> virtualTouchViewports) {
if (defaultViewport.valid) {
- setDisplayViewport(VIEWPORT_DEFAULT, defaultViewport);
+ setDisplayViewport(VIEWPORT_INTERNAL, defaultViewport);
}
if (externalTouchViewport.valid) {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index a54811b1a069..31cf9e346195 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -69,7 +69,6 @@ import android.os.WorkSource.WorkChain;
import android.provider.Settings;
import android.provider.Telephony.Carriers;
import android.telephony.CarrierConfigManager;
-import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
@@ -1577,6 +1576,8 @@ public class GnssLocationProvider implements LocationProviderInterface, InjectNt
mSingleShot = false;
native_stop();
mLastFixTime = 0;
+ // native_stop() may reset the position mode in hardware.
+ mLastPositionMode = null;
// reset SV count to zero
updateStatus(LocationProvider.TEMPORARILY_UNAVAILABLE);
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 91d4717ac23a..bdf12cad9cc1 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -334,9 +334,6 @@ public final class PowerManagerService extends SystemService
// True if boot completed occurred. We keep the screen on until this happens.
private boolean mBootCompleted;
- // Runnables that should be triggered on boot completed
- private Runnable[] mBootCompletedRunnables;
-
// True if auto-suspend mode is enabled.
// Refer to autosuspend.h.
private boolean mHalAutoSuspendModeEnabled;
@@ -732,14 +729,6 @@ public final class PowerManagerService extends SystemService
userActivityNoUpdateLocked(
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
-
- if (!ArrayUtils.isEmpty(mBootCompletedRunnables)) {
- Slog.d(TAG, "Posting " + mBootCompletedRunnables.length + " delayed runnables");
- for (Runnable r : mBootCompletedRunnables) {
- BackgroundThread.getHandler().post(r);
- }
- }
- mBootCompletedRunnables = null;
}
}
}
@@ -954,16 +943,6 @@ public final class PowerManagerService extends SystemService
mDirty |= DIRTY_SETTINGS;
}
- private void postAfterBootCompleted(Runnable r) {
- if (mBootCompleted) {
- BackgroundThread.getHandler().post(r);
- } else {
- Slog.d(TAG, "Delaying runnable until system is booted");
- mBootCompletedRunnables = ArrayUtils.appendElement(Runnable.class,
- mBootCompletedRunnables, r);
- }
- }
-
private void handleSettingsChangedLocked() {
updateSettingsLocked();
updatePowerStateLocked();
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index 41c0be63a5bb..b922e40a5d38 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -70,6 +70,7 @@ import com.android.internal.os.KernelUidCpuFreqTimeReader;
import com.android.internal.os.KernelUidCpuTimeReader;
import com.android.internal.os.KernelWakelockReader;
import com.android.internal.os.KernelWakelockStats;
+import com.android.internal.os.LooperStats;
import com.android.internal.os.PowerProfile;
import com.android.internal.util.DumpUtils;
import com.android.server.BinderCallsStatsService;
@@ -938,6 +939,29 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
}
+ private void pullLooperStats(int tagId, List<StatsLogEventWrapper> pulledData) {
+ LooperStats looperStats = LocalServices.getService(LooperStats.class);
+ if (looperStats == null) {
+ return;
+ }
+
+ List<LooperStats.ExportedEntry> entries = looperStats.getEntries();
+ long elapsedNanos = SystemClock.elapsedRealtimeNanos();
+ for (LooperStats.ExportedEntry entry : entries) {
+ StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 9 /* fields */);
+ e.writeLong(0); // uid collection not implemented yet
+ e.writeString(entry.handlerClassName);
+ e.writeString(entry.threadName);
+ e.writeString(entry.messageName);
+ e.writeLong(entry.messageCount);
+ e.writeLong(entry.exceptionCount);
+ e.writeLong(entry.recordedMessageCount);
+ e.writeLong(entry.totalLatencyMicros);
+ e.writeLong(entry.cpuUsageMicros);
+ pulledData.add(e);
+ }
+ }
+
/**
* Pulls various data.
*/
@@ -1028,6 +1052,10 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
pullBinderCallsStatsExceptions(tagId, ret);
break;
}
+ case StatsLog.LOOPER_STATS: {
+ pullLooperStats(tagId, ret);
+ break;
+ }
default:
Slog.w(TAG, "No such tagId data as " + tagId);
return null;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 32fa9bf97930..9490ae2a894a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1426,7 +1426,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
config.densityDpi = displayInfo.logicalDensityDpi;
config.colorMode =
- (displayInfo.isHdr()
+ ((displayInfo.isHdr() && mService.hasHdrSupport())
? Configuration.COLOR_MODE_HDR_YES
: Configuration.COLOR_MODE_HDR_NO)
| (displayInfo.isWideColorGamut() && mService.hasWideColorGamutSupport()
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e80a47eef2d5..2a381aca8a2a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -734,8 +734,9 @@ public class WindowManagerService extends IWindowManager.Stub
final DisplayManagerInternal mDisplayManagerInternal;
final DisplayManager mDisplayManager;
- // Indicates whether this device supports wide color gamut rendering
+ // Indicates whether this device supports wide color gamut / HDR rendering
private boolean mHasWideColorGamutSupport;
+ private boolean mHasHdrSupport;
// Who is holding the screen on.
private Session mHoldingScreenOn;
@@ -4504,6 +4505,7 @@ public class WindowManagerService extends IWindowManager.Stub
mPolicy.systemReady();
mTaskSnapshotController.systemReady();
mHasWideColorGamutSupport = queryWideColorGamutSupport();
+ mHasHdrSupport = queryHdrSupport();
}
private static boolean queryWideColorGamutSupport() {
@@ -4519,6 +4521,19 @@ public class WindowManagerService extends IWindowManager.Stub
return false;
}
+ private static boolean queryHdrSupport() {
+ try {
+ ISurfaceFlingerConfigs surfaceFlinger = ISurfaceFlingerConfigs.getService();
+ OptionalBool hasHdr = surfaceFlinger.hasHDRDisplay();
+ if (hasHdr != null) {
+ return hasHdr.value;
+ }
+ } catch (RemoteException e) {
+ // Ignore, we're in big trouble if we can't talk to SurfaceFlinger's config store
+ }
+ return false;
+ }
+
// -------------------------------------------------------------
// Async Handler
// -------------------------------------------------------------
@@ -7499,6 +7514,10 @@ public class WindowManagerService extends IWindowManager.Stub
SystemProperties.getInt("persist.sys.sf.native_mode", 0) != 1;
}
+ boolean hasHdrSupport() {
+ return mHasHdrSupport && hasWideColorGamutSupport();
+ }
+
void updateNonSystemOverlayWindowsVisibilityIfNeeded(WindowState win, boolean surfaceShown) {
if (!win.hideNonSystemOverlayWindowsWhenVisible()
&& !mHidingNonSystemOverlayWindows.contains(win)) {
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index 52f2d674f993..b467d61c355d 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -230,11 +230,11 @@ public:
virtual sp<PointerControllerInterface> obtainPointerController(int32_t deviceId);
virtual void notifyInputDevicesChanged(const Vector<InputDeviceInfo>& inputDevices);
virtual sp<KeyCharacterMap> getKeyboardLayoutOverlay(const InputDeviceIdentifier& identifier);
- virtual String8 getDeviceAlias(const InputDeviceIdentifier& identifier);
+ virtual std::string getDeviceAlias(const InputDeviceIdentifier& identifier);
virtual TouchAffineTransformation getTouchAffineTransformation(JNIEnv *env,
jfloatArray matrixArr);
virtual TouchAffineTransformation getTouchAffineTransformation(
- const String8& inputDeviceDescriptor, int32_t surfaceRotation);
+ const std::string& inputDeviceDescriptor, int32_t surfaceRotation);
/* --- InputDispatcherPolicyInterface implementation --- */
@@ -480,7 +480,7 @@ void NativeInputManager::getReaderConfiguration(InputReaderConfiguration* outCon
for (jsize i = 0; i < length; i++) {
jstring item = jstring(env->GetObjectArrayElement(excludedDeviceNames, i));
const char* deviceNameChars = env->GetStringUTFChars(item, NULL);
- outConfig->excludedDeviceNames.add(String8(deviceNameChars));
+ outConfig->excludedDeviceNames.push_back(deviceNameChars);
env->ReleaseStringUTFChars(item, deviceNameChars);
env->DeleteLocalRef(item);
}
@@ -606,7 +606,7 @@ sp<KeyCharacterMap> NativeInputManager::getKeyboardLayoutOverlay(
JNIEnv* env = jniEnv();
sp<KeyCharacterMap> result;
- ScopedLocalRef<jstring> descriptor(env, env->NewStringUTF(identifier.descriptor.string()));
+ ScopedLocalRef<jstring> descriptor(env, env->NewStringUTF(identifier.descriptor.c_str()));
ScopedLocalRef<jobject> identifierObj(env, env->NewObject(gInputDeviceIdentifierInfo.clazz,
gInputDeviceIdentifierInfo.constructor, descriptor.get(),
identifier.vendor, identifier.product));
@@ -620,24 +620,24 @@ sp<KeyCharacterMap> NativeInputManager::getKeyboardLayoutOverlay(
ScopedUtfChars filenameChars(env, filenameObj.get());
ScopedUtfChars contentsChars(env, contentsObj.get());
- KeyCharacterMap::loadContents(String8(filenameChars.c_str()),
- String8(contentsChars.c_str()), KeyCharacterMap::FORMAT_OVERLAY, &result);
+ KeyCharacterMap::loadContents(filenameChars.c_str(),
+ contentsChars.c_str(), KeyCharacterMap::FORMAT_OVERLAY, &result);
}
checkAndClearExceptionFromCallback(env, "getKeyboardLayoutOverlay");
return result;
}
-String8 NativeInputManager::getDeviceAlias(const InputDeviceIdentifier& identifier) {
+std::string NativeInputManager::getDeviceAlias(const InputDeviceIdentifier& identifier) {
ATRACE_CALL();
JNIEnv* env = jniEnv();
- ScopedLocalRef<jstring> uniqueIdObj(env, env->NewStringUTF(identifier.uniqueId.string()));
+ ScopedLocalRef<jstring> uniqueIdObj(env, env->NewStringUTF(identifier.uniqueId.c_str()));
ScopedLocalRef<jstring> aliasObj(env, jstring(env->CallObjectMethod(mServiceObj,
gServiceClassInfo.getDeviceAlias, uniqueIdObj.get())));
- String8 result;
+ std::string result;
if (aliasObj.get()) {
ScopedUtfChars aliasChars(env, aliasObj.get());
- result.setTo(aliasChars.c_str());
+ result = aliasChars.c_str();
}
checkAndClearExceptionFromCallback(env, "getDeviceAlias");
return result;
@@ -932,10 +932,10 @@ TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
}
TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
- const String8& inputDeviceDescriptor, int32_t surfaceRotation) {
+ const std::string& inputDeviceDescriptor, int32_t surfaceRotation) {
JNIEnv* env = jniEnv();
- ScopedLocalRef<jstring> descriptorObj(env, env->NewStringUTF(inputDeviceDescriptor.string()));
+ ScopedLocalRef<jstring> descriptorObj(env, env->NewStringUTF(inputDeviceDescriptor.c_str()));
jobject cal = env->CallObjectMethod(mServiceObj,
gServiceClassInfo.getTouchCalibrationForInputDevice, descriptorObj.get(),
@@ -1281,7 +1281,7 @@ static void nativeSetDisplayViewport(JNIEnv* env, jclass /* clazz */, jlong ptr,
v.deviceWidth = deviceWidth;
v.deviceHeight = deviceHeight;
if (uniqueId != nullptr) {
- v.uniqueId.setTo(ScopedUtfChars(env, uniqueId).c_str());
+ v.uniqueId = ScopedUtfChars(env, uniqueId).c_str();
}
im->setDisplayViewport(viewportType, v);
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ecc13b295539..6431344f218b 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -747,6 +747,11 @@ public final class SystemServer {
traceBeginAndSlog("StartBinderCallsStatsService");
mSystemServiceManager.startService(BinderCallsStatsService.LifeCycle.class);
traceEnd();
+
+ // Tracks time spent in handling messages in handlers.
+ traceBeginAndSlog("StartLooperStatsService");
+ mSystemServiceManager.startService(LooperStatsService.Lifecycle.class);
+ traceEnd();
}
/**
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 2f1c5169362a..4874bcef1606 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -44,6 +44,10 @@ public final class UsbAlsaManager {
private static final String TAG = UsbAlsaManager.class.getSimpleName();
private static final boolean DEBUG = false;
+ // Flag to turn on/off multi-peripheral select mode
+ // Set to true to have single-device-only mode
+ private static final boolean mIsSingleMode = true;
+
private static final String ALSA_DIRECTORY = "/dev/snd/";
private final Context mContext;
@@ -84,10 +88,11 @@ public final class UsbAlsaManager {
*/
private synchronized void selectAlsaDevice(UsbAlsaDevice alsaDevice) {
if (DEBUG) {
- Slog.d(TAG, "selectAlsaDevice " + alsaDevice);
+ Slog.d(TAG, "selectAlsaDevice() " + alsaDevice);
}
- if (mSelectedDevice != null) {
+ // This must be where an existing USB audio device is deselected.... (I think)
+ if (mIsSingleMode && mSelectedDevice != null) {
deselectAlsaDevice();
}
@@ -104,9 +109,15 @@ public final class UsbAlsaManager {
mSelectedDevice = alsaDevice;
alsaDevice.start();
+ if (DEBUG) {
+ Slog.d(TAG, "selectAlsaDevice() - done.");
+ }
}
private synchronized void deselectAlsaDevice() {
+ if (DEBUG) {
+ Slog.d(TAG, "deselectAlsaDevice() mSelectedDevice " + mSelectedDevice);
+ }
if (mSelectedDevice != null) {
mSelectedDevice.stop();
mSelectedDevice = null;
@@ -133,7 +144,7 @@ public final class UsbAlsaManager {
/* package */ UsbAlsaDevice selectDefaultDevice() {
if (DEBUG) {
- Slog.d(TAG, "UsbAudioManager.selectDefaultDevice()");
+ Slog.d(TAG, "selectDefaultDevice()");
}
if (mAlsaDevices.size() > 0) {
@@ -230,6 +241,8 @@ public final class UsbAlsaManager {
}
}
+ logDevices("deviceAdded()");
+
if (DEBUG) {
Slog.d(TAG, "deviceAdded() - done");
}
@@ -254,6 +267,9 @@ public final class UsbAlsaManager {
Slog.i(TAG, "USB MIDI Device Removed: " + usbMidiDevice);
IoUtils.closeQuietly(usbMidiDevice);
}
+
+ logDevices("usbDeviceRemoved()");
+
}
/* package */ void setPeripheralMidiState(boolean enabled, int card, int device) {
@@ -296,6 +312,7 @@ public final class UsbAlsaManager {
/**
* Dump the USB alsa state.
*/
+ // invoked with "adb shell dumpsys usb"
public void dump(DualDumpOutputStream dump, String idName, long id) {
long token = dump.start(idName, id);
@@ -314,29 +331,26 @@ public final class UsbAlsaManager {
dump.end(token);
}
-/*
public void logDevicesList(String title) {
- if (DEBUG) {
- for (HashMap.Entry<UsbDevice,UsbAlsaDevice> entry : mAudioDevices.entrySet()) {
- Slog.i(TAG, "UsbDevice-------------------");
- Slog.i(TAG, "" + (entry != null ? entry.getKey() : "[none]"));
- Slog.i(TAG, "UsbAlsaDevice--------------");
- Slog.i(TAG, "" + entry.getValue());
- }
- }
+ if (DEBUG) {
+ Slog.i(TAG, title + "----------------");
+ for (UsbAlsaDevice alsaDevice : mAlsaDevices) {
+ Slog.i(TAG, " -->");
+ Slog.i(TAG, "" + alsaDevice);
+ Slog.i(TAG, " <--");
+ }
+ Slog.i(TAG, "----------------");
+ }
}
-*/
// This logs a more terse (and more readable) version of the devices list
-/*
public void logDevices(String title) {
- if (DEBUG) {
- Slog.i(TAG, title);
- for (HashMap.Entry<UsbDevice,UsbAlsaDevice> entry : mAudioDevices.entrySet()) {
- Slog.i(TAG, entry.getValue().toShortString());
- }
- }
+ if (DEBUG) {
+ Slog.i(TAG, title + "----------------");
+ for (UsbAlsaDevice alsaDevice : mAlsaDevices) {
+ Slog.i(TAG, alsaDevice.toShortString());
+ }
+ Slog.i(TAG, "----------------");
+ }
}
-*/
-
}
diff --git a/services/usb/java/com/android/server/usb/UsbHandlerManager.java b/services/usb/java/com/android/server/usb/UsbHandlerManager.java
new file mode 100644
index 000000000000..1730d8f22950
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/UsbHandlerManager.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.usb;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.hardware.usb.UsbAccessory;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbManager;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import java.util.ArrayList;
+
+/**
+ * UsbResolveActivityManager creates UI dialogs for user to pick or confirm handler for
+ * usb attach event.
+ *
+ * @hide
+ */
+class UsbHandlerManager {
+ private static final String LOG_TAG = UsbHandlerManager.class.getSimpleName();
+
+ private final Context mContext;
+
+ UsbHandlerManager(@NonNull Context context) {
+ mContext = context;
+ }
+
+ /**
+ * Shows dialog to user to allow them to optionally visit that URL for more
+ * information or software downloads if the attached USB accessory has a valid
+ * URL associated with it.
+ *
+ * @param accessory The accessory to confirm in the UI dialog
+ * @param user The user to start the UI dialog
+ */
+ void showUsbAccessoryUriActivity(@NonNull UsbAccessory accessory,
+ @NonNull UserHandle user) {
+ String uri = accessory.getUri();
+ if (uri != null && uri.length() > 0) {
+ // display URI to user
+ Intent dialogIntent = createDialogIntent();
+ dialogIntent.setClassName("com.android.systemui",
+ "com.android.systemui.usb.UsbAccessoryUriActivity");
+ dialogIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
+ dialogIntent.putExtra("uri", uri);
+ try {
+ mContext.startActivityAsUser(dialogIntent, user);
+ } catch (ActivityNotFoundException e) {
+ Slog.e(LOG_TAG, "unable to start UsbAccessoryUriActivity");
+ }
+ }
+ }
+
+ /**
+ * Shows dialog to user to confirm the package to start when the USB device
+ * or accessory is attached and there is only one package claims to handle this
+ * USB device or accessory.
+ *
+ * @param rInfo The ResolveInfo of the package to confirm in the UI dialog
+ * @param device The USB device to confirm
+ * @param accessory The USB accessory to confirm
+ */
+ void confirmUsbHandler(@NonNull ResolveInfo rInfo, @Nullable UsbDevice device,
+ @Nullable UsbAccessory accessory) {
+ Intent resolverIntent = createDialogIntent();
+ // start UsbConfirmActivity if there is only one choice
+ resolverIntent.setClassName("com.android.systemui",
+ "com.android.systemui.usb.UsbConfirmActivity");
+ resolverIntent.putExtra("rinfo", rInfo);
+ UserHandle user =
+ UserHandle.getUserHandleForUid(rInfo.activityInfo.applicationInfo.uid);
+
+ if (device != null) {
+ resolverIntent.putExtra(UsbManager.EXTRA_DEVICE, device);
+ } else {
+ resolverIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
+ }
+
+ try {
+ mContext.startActivityAsUser(resolverIntent, user);
+ } catch (ActivityNotFoundException e) {
+ Slog.e(LOG_TAG, "unable to start activity " + resolverIntent, e);
+ }
+ }
+
+ /**
+ * Shows dialog to user to select the package to start when the USB device
+ * or accessory is attached and there are more than one package claim to handle this
+ * USB device or accessory.
+ *
+ * @param matches The available resolutions of the intent
+ * @param user The user to start UI dialog
+ * @param intent The intent to start the UI dialog
+ */
+ void selectUsbHandler(@NonNull ArrayList<ResolveInfo> matches,
+ @NonNull UserHandle user, @NonNull Intent intent) {
+ Intent resolverIntent = createDialogIntent();
+ resolverIntent.setClassName("com.android.systemui",
+ "com.android.systemui.usb.UsbResolverActivity");
+ resolverIntent.putParcelableArrayListExtra("rlist", matches);
+ resolverIntent.putExtra(Intent.EXTRA_INTENT, intent);
+
+ try {
+ mContext.startActivityAsUser(resolverIntent, user);
+ } catch (ActivityNotFoundException e) {
+ Slog.e(LOG_TAG, "unable to start activity " + resolverIntent, e);
+ }
+ }
+
+ private Intent createDialogIntent() {
+ Intent intent = new Intent();
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ return intent;
+ }
+}
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index 67ad0907181b..589bcdc14871 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -408,11 +408,15 @@ public class UsbHostManager {
/* Called from JNI in monitorUsbHostBus to report USB device removal */
@SuppressWarnings("unused")
private void usbDeviceRemoved(String deviceAddress) {
+ if (DEBUG) {
+ Slog.d(TAG, "usbDeviceRemoved(" + deviceAddress + ") end");
+ }
+
synchronized (mLock) {
UsbDevice device = mDevices.remove(deviceAddress);
if (device != null) {
Slog.d(TAG, "Removed device at " + deviceAddress + ": " + device.getProductName());
- mUsbAlsaManager.usbDeviceRemoved(deviceAddress/*device*/);
+ mUsbAlsaManager.usbDeviceRemoved(deviceAddress);
mSettingsManager.usbDeviceRemoved(device);
getCurrentUserSettings().usbDeviceRemoved(device);
diff --git a/services/usb/java/com/android/server/usb/UsbPermissionManager.java b/services/usb/java/com/android/server/usb/UsbPermissionManager.java
new file mode 100644
index 000000000000..2c9ee36107e8
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/UsbPermissionManager.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.usb;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.content.ActivityNotFoundException;
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.usb.UsbAccessory;
+import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbManager;
+import android.os.Binder;
+import android.os.Process;
+import android.os.UserHandle;
+import android.service.usb.UsbSettingsAccessoryPermissionProto;
+import android.service.usb.UsbSettingsDevicePermissionProto;
+import android.service.usb.UsbUserSettingsManagerProto;
+import android.util.Slog;
+import android.util.SparseBooleanArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.dump.DualDumpOutputStream;
+
+import java.util.HashMap;
+
+/**
+ * UsbPermissionManager manages usb device or accessory access permissions.
+ *
+ * @hide
+ */
+class UsbPermissionManager {
+ private static final String LOG_TAG = UsbPermissionManager.class.getSimpleName();
+
+ @GuardedBy("mLock")
+ /** Temporary mapping USB device name to list of UIDs with permissions for the device*/
+ private final HashMap<String, SparseBooleanArray> mDevicePermissionMap =
+ new HashMap<>();
+ @GuardedBy("mLock")
+ /** Temporary mapping UsbAccessory to list of UIDs with permissions for the accessory*/
+ private final HashMap<UsbAccessory, SparseBooleanArray> mAccessoryPermissionMap =
+ new HashMap<>();
+
+ private final UserHandle mUser;
+ private final boolean mDisablePermissionDialogs;
+
+ private final Object mLock = new Object();
+
+ UsbPermissionManager(@NonNull Context context, @NonNull UserHandle user) {
+ mUser = user;
+ mDisablePermissionDialogs = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_disableUsbPermissionDialogs);
+ }
+
+ /**
+ * Removes access permissions of all packages for the USB accessory.
+ *
+ * @param accessory to remove permissions for
+ */
+ void removeAccessoryPermissions(@NonNull UsbAccessory accessory) {
+ synchronized (mLock) {
+ mAccessoryPermissionMap.remove(accessory);
+ }
+ }
+
+ /**
+ * Removes access permissions of all packages for the USB device.
+ *
+ * @param device to remove permissions for
+ */
+ void removeDevicePermissions(@NonNull UsbDevice device) {
+ synchronized (mLock) {
+ mDevicePermissionMap.remove(device.getDeviceName());
+ }
+ }
+
+ /**
+ * Grants permission for USB device without showing system dialog for package with uid.
+ *
+ * @param device to grant permission for
+ * @param uid to grant permission for
+ */
+ void grantDevicePermission(@NonNull UsbDevice device, int uid) {
+ synchronized (mLock) {
+ String deviceName = device.getDeviceName();
+ SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName);
+ if (uidList == null) {
+ uidList = new SparseBooleanArray(1);
+ mDevicePermissionMap.put(deviceName, uidList);
+ }
+ uidList.put(uid, true);
+ }
+ }
+
+ /**
+ * Grants permission for USB accessory without showing system dialog for package with uid.
+ *
+ * @param accessory to grant permission for
+ * @param uid to grant permission for
+ */
+ void grantAccessoryPermission(@NonNull UsbAccessory accessory, int uid) {
+ synchronized (mLock) {
+ SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
+ if (uidList == null) {
+ uidList = new SparseBooleanArray(1);
+ mAccessoryPermissionMap.put(accessory, uidList);
+ }
+ uidList.put(uid, true);
+ }
+ }
+
+ /**
+ * Returns true if package with uid has permission to access the device.
+ *
+ * @param device to check permission for
+ * @param uid to check permission for
+ * @return {@code true} if package with uid has permission
+ */
+ boolean hasPermission(@NonNull UsbDevice device, int uid) {
+ synchronized (mLock) {
+ if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
+ return true;
+ }
+ SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName());
+ if (uidList == null) {
+ return false;
+ }
+ return uidList.get(uid);
+ }
+ }
+
+ /**
+ * Returns true if caller has permission to access the accessory.
+ *
+ * @param accessory to check permission for
+ * @return {@code true} if caller has permssion
+ */
+ boolean hasPermission(@NonNull UsbAccessory accessory) {
+ synchronized (mLock) {
+ int uid = Binder.getCallingUid();
+ if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
+ return true;
+ }
+ SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
+ if (uidList == null) {
+ return false;
+ }
+ return uidList.get(uid);
+ }
+ }
+
+ /**
+ * Creates UI dialog to request permission for the given package to access the device
+ * or accessory.
+ *
+ * @param device The USB device attached
+ * @param accessory The USB accessory attached
+ * @param canBeDefault Whether the calling pacakge can set as default handler
+ * of the USB device or accessory
+ * @param packageName The package name of the calling package
+ * @param uid The uid of the calling package
+ * @param userContext The context to start the UI dialog
+ * @param pi PendingIntent for returning result
+ */
+ void requestPermissionDialog(@Nullable UsbDevice device,
+ @Nullable UsbAccessory accessory,
+ boolean canBeDefault,
+ @NonNull String packageName,
+ int uid,
+ @NonNull Context userContext,
+ @NonNull PendingIntent pi) {
+ long identity = Binder.clearCallingIdentity();
+ Intent intent = new Intent();
+ if (device != null) {
+ intent.putExtra(UsbManager.EXTRA_DEVICE, device);
+ } else {
+ intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
+ }
+ intent.putExtra(Intent.EXTRA_INTENT, pi);
+ intent.putExtra(Intent.EXTRA_UID, uid);
+ intent.putExtra(UsbManager.EXTRA_CAN_BE_DEFAULT, canBeDefault);
+ intent.putExtra(UsbManager.EXTRA_PACKAGE, packageName);
+ intent.setClassName("com.android.systemui",
+ "com.android.systemui.usb.UsbPermissionActivity");
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ try {
+ userContext.startActivityAsUser(intent, mUser);
+ } catch (ActivityNotFoundException e) {
+ Slog.e(LOG_TAG, "unable to start UsbPermissionActivity");
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ void dump(@NonNull DualDumpOutputStream dump) {
+ synchronized (mLock) {
+ for (String deviceName : mDevicePermissionMap.keySet()) {
+ long devicePermissionToken = dump.start("device_permissions",
+ UsbUserSettingsManagerProto.DEVICE_PERMISSIONS);
+
+ dump.write("device_name", UsbSettingsDevicePermissionProto.DEVICE_NAME, deviceName);
+
+ SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName);
+ int count = uidList.size();
+ for (int i = 0; i < count; i++) {
+ dump.write("uids", UsbSettingsDevicePermissionProto.UIDS, uidList.keyAt(i));
+ }
+
+ dump.end(devicePermissionToken);
+ }
+
+ for (UsbAccessory accessory : mAccessoryPermissionMap.keySet()) {
+ long accessoryPermissionToken = dump.start("accessory_permissions",
+ UsbUserSettingsManagerProto.ACCESSORY_PERMISSIONS);
+
+ dump.write("accessory_description",
+ UsbSettingsAccessoryPermissionProto.ACCESSORY_DESCRIPTION,
+ accessory.getDescription());
+
+ SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
+ int count = uidList.size();
+ for (int i = 0; i < count; i++) {
+ dump.write("uids", UsbSettingsAccessoryPermissionProto.UIDS, uidList.keyAt(i));
+ }
+
+ dump.end(accessoryPermissionToken);
+ }
+ }
+ }
+}
diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
index 7a906d0b7aaf..1ab1f7e43906 100644
--- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java
@@ -193,6 +193,8 @@ class UsbProfileGroupSettingsManager {
MyPackageMonitor mPackageMonitor = new MyPackageMonitor();
+ private final UsbHandlerManager mUsbHandlerManager;
+
private final MtpNotificationManager mMtpNotificationManager;
/**
@@ -201,9 +203,11 @@ class UsbProfileGroupSettingsManager {
* @param context The context of the service
* @param user The parent profile
* @param settingsManager The settings manager of the service
+ * @param usbResolveActivityManager The resovle activity manager of the service
*/
UsbProfileGroupSettingsManager(@NonNull Context context, @NonNull UserHandle user,
- @NonNull UsbSettingsManager settingsManager) {
+ @NonNull UsbSettingsManager settingsManager,
+ @NonNull UsbHandlerManager usbResolveActivityManager) {
if (DEBUG) Slog.v(TAG, "Creating settings for " + user);
Context parentUserContext;
@@ -238,6 +242,8 @@ class UsbProfileGroupSettingsManager {
parentUserContext,
device -> resolveActivity(createDeviceAttachedIntent(device),
device, false /* showMtpNotification */));
+
+ mUsbHandlerManager = usbResolveActivityManager;
}
/**
@@ -830,23 +836,8 @@ class UsbProfileGroupSettingsManager {
// don't show the resolver activity if there are no choices available
if (matches.size() == 0) {
if (accessory != null) {
- String uri = accessory.getUri();
- if (uri != null && uri.length() > 0) {
- // display URI to user
- Intent dialogIntent = new Intent();
- dialogIntent.setClassName("com.android.systemui",
- "com.android.systemui.usb.UsbAccessoryUriActivity");
- dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- dialogIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
- dialogIntent.putExtra("uri", uri);
- try {
- mContext.startActivityAsUser(dialogIntent, mParentUser);
- } catch (ActivityNotFoundException e) {
- Slog.e(TAG, "unable to start UsbAccessoryUriActivity");
- }
- }
+ mUsbHandlerManager.showUsbAccessoryUriActivity(accessory, mParentUser);
}
-
// do nothing
return;
}
@@ -875,37 +866,10 @@ class UsbProfileGroupSettingsManager {
Slog.e(TAG, "startActivity failed", e);
}
} else {
- Intent resolverIntent = new Intent();
- resolverIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- UserHandle user;
-
if (matches.size() == 1) {
- ResolveInfo rInfo = matches.get(0);
-
- // start UsbConfirmActivity if there is only one choice
- resolverIntent.setClassName("com.android.systemui",
- "com.android.systemui.usb.UsbConfirmActivity");
- resolverIntent.putExtra("rinfo", rInfo);
- user = UserHandle.getUserHandleForUid(rInfo.activityInfo.applicationInfo.uid);
-
- if (device != null) {
- resolverIntent.putExtra(UsbManager.EXTRA_DEVICE, device);
- } else {
- resolverIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
- }
+ mUsbHandlerManager.confirmUsbHandler(matches.get(0), device, accessory);
} else {
- user = mParentUser;
-
- // start UsbResolverActivity so user can choose an activity
- resolverIntent.setClassName("com.android.systemui",
- "com.android.systemui.usb.UsbResolverActivity");
- resolverIntent.putParcelableArrayListExtra("rlist", matches);
- resolverIntent.putExtra(Intent.EXTRA_INTENT, intent);
- }
- try {
- mContext.startActivityAsUser(resolverIntent, user);
- } catch (ActivityNotFoundException e) {
- Slog.e(TAG, "unable to start activity " + resolverIntent, e);
+ mUsbHandlerManager.selectUsbHandler(matches, mParentUser, intent);
}
}
}
diff --git a/services/usb/java/com/android/server/usb/UsbSettingsManager.java b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
index 9221825b2d87..27566f04c280 100644
--- a/services/usb/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbSettingsManager.java
@@ -57,10 +57,12 @@ class UsbSettingsManager {
private final SparseArray<UsbProfileGroupSettingsManager> mSettingsByProfileGroup
= new SparseArray<>();
private UserManager mUserManager;
+ private UsbHandlerManager mUsbHandlerManager;
public UsbSettingsManager(@NonNull Context context) {
mContext = context;
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ mUsbHandlerManager = new UsbHandlerManager(context);
}
/**
@@ -74,7 +76,8 @@ class UsbSettingsManager {
synchronized (mSettingsByUser) {
UsbUserSettingsManager settings = mSettingsByUser.get(userId);
if (settings == null) {
- settings = new UsbUserSettingsManager(mContext, new UserHandle(userId));
+ settings = new UsbUserSettingsManager(mContext, UserHandle.of(userId),
+ new UsbPermissionManager(mContext, UserHandle.of(userId)));
mSettingsByUser.put(userId, settings);
}
return settings;
@@ -102,7 +105,8 @@ class UsbSettingsManager {
UsbProfileGroupSettingsManager settings = mSettingsByProfileGroup.get(
parentUser.getIdentifier());
if (settings == null) {
- settings = new UsbProfileGroupSettingsManager(mContext, parentUser, this);
+ settings = new UsbProfileGroupSettingsManager(mContext, parentUser, this,
+ mUsbHandlerManager);
mSettingsByProfileGroup.put(parentUser.getIdentifier(), settings);
}
return settings;
diff --git a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
index 24a2d72415ed..fe93399c2d60 100644
--- a/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
+++ b/services/usb/java/com/android/server/usb/UsbUserSettingsManager.java
@@ -21,15 +21,18 @@ import static com.android.server.usb.UsbProfileGroupSettingsManager.getAccessory
import static com.android.server.usb.UsbProfileGroupSettingsManager.getDeviceFilters;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.PendingIntent;
-import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
+import android.content.res.XmlResourceParser;
import android.hardware.usb.AccessoryFilter;
import android.hardware.usb.DeviceFilter;
import android.hardware.usb.UsbAccessory;
@@ -38,42 +41,34 @@ import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Binder;
-import android.os.Process;
import android.os.UserHandle;
import android.service.usb.UsbAccessoryAttachedActivities;
import android.service.usb.UsbDeviceAttachedActivities;
-import android.service.usb.UsbSettingsAccessoryPermissionProto;
-import android.service.usb.UsbSettingsDevicePermissionProto;
import android.service.usb.UsbUserSettingsManagerProto;
import android.util.Slog;
-import android.util.SparseBooleanArray;
+import com.android.internal.util.XmlUtils;
import com.android.internal.util.dump.DualDumpOutputStream;
+import org.xmlpull.v1.XmlPullParser;
+
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
class UsbUserSettingsManager {
- private static final String TAG = "UsbUserSettingsManager";
+ private static final String TAG = UsbUserSettingsManager.class.getSimpleName();
private static final boolean DEBUG = false;
private final UserHandle mUser;
- private final boolean mDisablePermissionDialogs;
private final Context mUserContext;
private final PackageManager mPackageManager;
-
- // Temporary mapping USB device name to list of UIDs with permissions for the device
- private final HashMap<String, SparseBooleanArray> mDevicePermissionMap =
- new HashMap<>();
- // Temporary mapping UsbAccessory to list of UIDs with permissions for the accessory
- private final HashMap<UsbAccessory, SparseBooleanArray> mAccessoryPermissionMap =
- new HashMap<>();
+ private final UsbPermissionManager mUsbPermissionManager;
private final Object mLock = new Object();
- public UsbUserSettingsManager(Context context, UserHandle user) {
+ UsbUserSettingsManager(Context context, UserHandle user,
+ @NonNull UsbPermissionManager usbPermissionManager) {
if (DEBUG) Slog.v(TAG, "Creating settings for " + user);
try {
@@ -85,9 +80,7 @@ class UsbUserSettingsManager {
mPackageManager = mUserContext.getPackageManager();
mUser = user;
-
- mDisablePermissionDialogs = context.getResources().getBoolean(
- com.android.internal.R.bool.config_disableUsbPermissionDialogs);
+ mUsbPermissionManager = usbPermissionManager;
}
/**
@@ -96,9 +89,7 @@ class UsbUserSettingsManager {
* @param device The device the permissions are for
*/
void removeDevicePermissions(@NonNull UsbDevice device) {
- synchronized (mLock) {
- mDevicePermissionMap.remove(device.getDeviceName());
- }
+ mUsbPermissionManager.removeDevicePermissions(device);
}
/**
@@ -107,9 +98,7 @@ class UsbUserSettingsManager {
* @param accessory The accessory the permissions are for
*/
void removeAccessoryPermissions(@NonNull UsbAccessory accessory) {
- synchronized (mLock) {
- mAccessoryPermissionMap.remove(accessory);
- }
+ mUsbPermissionManager.removeAccessoryPermissions(accessory);
}
/**
@@ -170,35 +159,17 @@ class UsbUserSettingsManager {
}
public boolean hasPermission(UsbDevice device, String packageName, int uid) {
- synchronized (mLock) {
- if (isCameraDevicePresent(device)) {
- if (!isCameraPermissionGranted(packageName, uid)) {
- return false;
- }
- }
- if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
- return true;
- }
- SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName());
- if (uidList == null) {
+ if (isCameraDevicePresent(device)) {
+ if (!isCameraPermissionGranted(packageName, uid)) {
return false;
}
- return uidList.get(uid);
}
+
+ return mUsbPermissionManager.hasPermission(device, uid);
}
public boolean hasPermission(UsbAccessory accessory) {
- synchronized (mLock) {
- int uid = Binder.getCallingUid();
- if (uid == Process.SYSTEM_UID || mDisablePermissionDialogs) {
- return true;
- }
- SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
- if (uidList == null) {
- return false;
- }
- return uidList.get(uid);
- }
+ return mUsbPermissionManager.hasPermission(accessory);
}
public void checkPermission(UsbDevice device, String packageName, int uid) {
@@ -213,7 +184,11 @@ class UsbUserSettingsManager {
}
}
- private void requestPermissionDialog(Intent intent, String packageName, PendingIntent pi) {
+ private void requestPermissionDialog(@Nullable UsbDevice device,
+ @Nullable UsbAccessory accessory,
+ boolean canBeDefault,
+ String packageName,
+ PendingIntent pi) {
final int uid = Binder.getCallingUid();
// compare uid with packageName to foil apps pretending to be someone else
@@ -227,27 +202,15 @@ class UsbUserSettingsManager {
throw new IllegalArgumentException("package " + packageName + " not found");
}
- long identity = Binder.clearCallingIdentity();
- intent.setClassName("com.android.systemui",
- "com.android.systemui.usb.UsbPermissionActivity");
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(Intent.EXTRA_INTENT, pi);
- intent.putExtra("package", packageName);
- intent.putExtra(Intent.EXTRA_UID, uid);
- try {
- mUserContext.startActivityAsUser(intent, mUser);
- } catch (ActivityNotFoundException e) {
- Slog.e(TAG, "unable to start UsbPermissionActivity");
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
+ mUsbPermissionManager.requestPermissionDialog(device,
+ accessory, canBeDefault, packageName, uid, mUserContext, pi);
}
public void requestPermission(UsbDevice device, String packageName, PendingIntent pi, int uid) {
- Intent intent = new Intent();
+ Intent intent = new Intent();
// respond immediately if permission has already been granted
- if (hasPermission(device, packageName, uid)) {
+ if (hasPermission(device, packageName, uid)) {
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
try {
@@ -270,16 +233,13 @@ class UsbUserSettingsManager {
}
}
- // start UsbPermissionActivity so user can choose an activity
- intent.putExtra(UsbManager.EXTRA_DEVICE, device);
- requestPermissionDialog(intent, packageName, pi);
+ requestPermissionDialog(device, null, canBeDefault(device, packageName), packageName, pi);
}
public void requestPermission(UsbAccessory accessory, String packageName, PendingIntent pi) {
- Intent intent = new Intent();
-
// respond immediately if permission has already been granted
if (hasPermission(accessory)) {
+ Intent intent = new Intent();
intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true);
try {
@@ -290,31 +250,16 @@ class UsbUserSettingsManager {
return;
}
- intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory);
- requestPermissionDialog(intent, packageName, pi);
+ requestPermissionDialog(null, accessory,
+ canBeDefault(accessory, packageName), packageName, pi);
}
public void grantDevicePermission(UsbDevice device, int uid) {
- synchronized (mLock) {
- String deviceName = device.getDeviceName();
- SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName);
- if (uidList == null) {
- uidList = new SparseBooleanArray(1);
- mDevicePermissionMap.put(deviceName, uidList);
- }
- uidList.put(uid, true);
- }
+ mUsbPermissionManager.grantDevicePermission(device, uid);
}
public void grantAccessoryPermission(UsbAccessory accessory, int uid) {
- synchronized (mLock) {
- SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
- if (uidList == null) {
- uidList = new SparseBooleanArray(1);
- mAccessoryPermissionMap.put(accessory, uidList);
- }
- uidList.put(uid, true);
- }
+ mUsbPermissionManager.grantAccessoryPermission(accessory, uid);
}
/**
@@ -329,42 +274,108 @@ class UsbUserSettingsManager {
mUser.getIdentifier());
}
- public void dump(@NonNull DualDumpOutputStream dump, @NonNull String idName, long id) {
- long token = dump.start(idName, id);
+ /**
+ * Can the app be the default for the USB device. I.e. can the app be launched by default if
+ * the device is plugged in.
+ *
+ * @param device The device the app would be default for
+ * @param packageName The package name of the app
+ *
+ * @return {@code true} if the app can be default
+ */
+ private boolean canBeDefault(@NonNull UsbDevice device, String packageName) {
+ ActivityInfo[] activities = getPackageActivities(packageName);
+ if (activities != null) {
+ int numActivities = activities.length;
+ for (int i = 0; i < numActivities; i++) {
+ ActivityInfo activityInfo = activities[i];
+
+ try (XmlResourceParser parser = activityInfo.loadXmlMetaData(mPackageManager,
+ UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
+ if (parser == null) {
+ continue;
+ }
- synchronized (mLock) {
- dump.write("user_id", UsbUserSettingsManagerProto.USER_ID, mUser.getIdentifier());
+ XmlUtils.nextElement(parser);
+ while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+ if ("usb-device".equals(parser.getName())) {
+ DeviceFilter filter = DeviceFilter.read(parser);
+ if (filter.matches(device)) {
+ return true;
+ }
+ }
- for (String deviceName : mDevicePermissionMap.keySet()) {
- long devicePermissionToken = dump.start("device_permissions",
- UsbUserSettingsManagerProto.DEVICE_PERMISSIONS);
+ XmlUtils.nextElement(parser);
+ }
+ } catch (Exception e) {
+ Slog.w(TAG, "Unable to load component info " + activityInfo.toString(), e);
+ }
+ }
+ }
- dump.write("device_name", UsbSettingsDevicePermissionProto.DEVICE_NAME, deviceName);
+ return false;
+ }
- SparseBooleanArray uidList = mDevicePermissionMap.get(deviceName);
- int count = uidList.size();
- for (int i = 0; i < count; i++) {
- dump.write("uids", UsbSettingsDevicePermissionProto.UIDS, uidList.keyAt(i));
- }
+ /**
+ * Can the app be the default for the USB accessory. I.e. can the app be launched by default if
+ * the accessory is plugged in.
+ *
+ * @param accessory The accessory the app would be default for
+ * @param packageName The package name of the app
+ *
+ * @return {@code true} if the app can be default
+ */
+ private boolean canBeDefault(@NonNull UsbAccessory accessory, String packageName) {
+ ActivityInfo[] activities = getPackageActivities(packageName);
+ if (activities != null) {
+ int numActivities = activities.length;
+ for (int i = 0; i < numActivities; i++) {
+ ActivityInfo activityInfo = activities[i];
+
+ try (XmlResourceParser parser = activityInfo.loadXmlMetaData(mPackageManager,
+ UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) {
+ if (parser == null) {
+ continue;
+ }
- dump.end(devicePermissionToken);
- }
- for (UsbAccessory accessory : mAccessoryPermissionMap.keySet()) {
- long accessoryPermissionToken = dump.start("accessory_permissions",
- UsbUserSettingsManagerProto.ACCESSORY_PERMISSIONS);
-
- dump.write("accessory_description",
- UsbSettingsAccessoryPermissionProto.ACCESSORY_DESCRIPTION,
- accessory.getDescription());
-
- SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory);
- int count = uidList.size();
- for (int i = 0; i < count; i++) {
- dump.write("uids", UsbSettingsAccessoryPermissionProto.UIDS, uidList.keyAt(i));
- }
+ XmlUtils.nextElement(parser);
+ while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
+ if ("usb-accessory".equals(parser.getName())) {
+ AccessoryFilter filter = AccessoryFilter.read(parser);
+ if (filter.matches(accessory)) {
+ return true;
+ }
+ }
- dump.end(accessoryPermissionToken);
+ XmlUtils.nextElement(parser);
+ }
+ } catch (Exception e) {
+ Slog.w(TAG, "Unable to load component info " + activityInfo.toString(), e);
+ }
}
+ }
+
+ return false;
+ }
+
+ private ActivityInfo[] getPackageActivities(String packageName) {
+ try {
+ PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName,
+ PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA);
+ return packageInfo.activities;
+ } catch (PackageManager.NameNotFoundException e) {
+ // ignore
+ }
+ return null;
+ }
+
+ public void dump(@NonNull DualDumpOutputStream dump, @NonNull String idName, long id) {
+ long token = dump.start(idName, id);
+
+ synchronized (mLock) {
+ dump.write("user_id", UsbUserSettingsManagerProto.USER_ID, mUser.getIdentifier());
+
+ mUsbPermissionManager.dump(dump);
List<ResolveInfo> deviceAttachedActivities = queryIntentActivities(
new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED));
diff --git a/tools/validatekeymaps/Android.bp b/tools/validatekeymaps/Android.bp
index 6fb278c83f0a..819e75ba1fed 100644
--- a/tools/validatekeymaps/Android.bp
+++ b/tools/validatekeymaps/Android.bp
@@ -15,6 +15,7 @@ cc_binary_host {
],
static_libs: [
+ "libbase",
"libinput",
"libutils",
"libcutils",
diff --git a/tools/validatekeymaps/Main.cpp b/tools/validatekeymaps/Main.cpp
index bbfcba6272b2..f31f771004bd 100644
--- a/tools/validatekeymaps/Main.cpp
+++ b/tools/validatekeymaps/Main.cpp
@@ -18,7 +18,6 @@
#include <input/KeyLayoutMap.h>
#include <input/VirtualKeyMap.h>
#include <utils/PropertyMap.h>
-#include <utils/String8.h>
#include <stdarg.h>
#include <stdio.h>
@@ -98,7 +97,7 @@ static bool validateFile(const char* filename) {
case FILETYPE_KEYLAYOUT: {
sp<KeyLayoutMap> map;
- status_t status = KeyLayoutMap::load(String8(filename), &map);
+ status_t status = KeyLayoutMap::load(filename, &map);
if (status) {
error("Error %d parsing key layout file.\n\n", status);
return false;
@@ -108,7 +107,7 @@ static bool validateFile(const char* filename) {
case FILETYPE_KEYCHARACTERMAP: {
sp<KeyCharacterMap> map;
- status_t status = KeyCharacterMap::load(String8(filename),
+ status_t status = KeyCharacterMap::load(filename,
KeyCharacterMap::FORMAT_ANY, &map);
if (status) {
error("Error %d parsing key character map file.\n\n", status);
@@ -130,7 +129,7 @@ static bool validateFile(const char* filename) {
case FILETYPE_VIRTUALKEYDEFINITION: {
VirtualKeyMap* map;
- status_t status = VirtualKeyMap::load(String8(filename), &map);
+ status_t status = VirtualKeyMap::load(filename, &map);
if (status) {
error("Error %d parsing virtual key definition file.\n\n", status);
return false;
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
index 7c99c497c54b..14263830660f 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java
@@ -48,7 +48,7 @@ public class WifiAwareAgentNetworkSpecifier extends NetworkSpecifier implements
private MessageDigest mDigester;
public WifiAwareAgentNetworkSpecifier() {
- // do nothing, already initialized to empty
+ initialize();
}
public WifiAwareAgentNetworkSpecifier(WifiAwareNetworkSpecifier ns) {
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
index 0515e0637e03..657e5a70b53d 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareAgentNetworkSpecifierTest.java
@@ -18,6 +18,7 @@ package android.net.wifi.aware;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import android.os.Parcel;
import android.support.test.filters.SmallTest;
@@ -60,6 +61,13 @@ public class WifiAwareAgentNetworkSpecifierTest {
WifiAwareAgentNetworkSpecifier.CREATOR.createFromParcel(parcelR);
assertEquals(dut, rereadDut);
+
+ // Ensure that individual network specifiers are satisfied by both the original & marshaled
+ // |WifiAwareNetworkAgentSpecifier instances.
+ for (WifiAwareNetworkSpecifier ns : nsSet) {
+ assertTrue(dut.satisfiesAwareNetworkSpecifier(ns));
+ assertTrue(rereadDut.satisfiesAwareNetworkSpecifier(ns));
+ }
}
/**