Merge "Fix default grant running for secondary user."
diff --git a/Android.bp b/Android.bp
index 072007b..1ee7405 100644
--- a/Android.bp
+++ b/Android.bp
@@ -773,7 +773,7 @@
"android.hardware.vibrator-V1.2-java",
"android.hardware.vibrator-V1.3-java",
"android.hardware.wifi-V1.0-java-constants",
- "networkstack-aidl-interfaces-java",
+ "networkstack-aidl-framework-java",
"netd_aidl_parcelables-java",
"devicepolicyprotosnano",
],
@@ -896,7 +896,6 @@
"core/java/android/net/DhcpResultsParcelable.aidl",
"core/java/android/net/INetworkMonitor.aidl",
"core/java/android/net/INetworkMonitorCallbacks.aidl",
- "core/java/android/net/IIpMemoryStore.aidl",
"core/java/android/net/INetworkStackConnector.aidl",
"core/java/android/net/INetworkStackStatusCallback.aidl",
"core/java/android/net/InitialConfigurationParcelable.aidl",
@@ -915,6 +914,16 @@
"core/java/android/net/dhcp/IDhcpServerCallbacks.aidl",
"core/java/android/net/ip/IIpClient.aidl",
"core/java/android/net/ip/IIpClientCallbacks.aidl",
+ ],
+ api_dir: "aidl/networkstack",
+}
+
+aidl_interface {
+ name: "networkstack-aidl-framework",
+ local_include_dir: "core/java",
+ srcs: [
+ "core/java/android/net/TcpKeepalivePacketDataParcelable.aidl",
+ "core/java/android/net/IIpMemoryStore.aidl",
"core/java/android/net/ipmemorystore/**/*.aidl",
],
api_dir: "aidl/networkstack",
diff --git a/api/current.txt b/api/current.txt
index 9cd33e6..fe86cbe 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -49267,6 +49267,7 @@
ctor public ContextThemeWrapper(android.content.Context, android.content.res.Resources.Theme);
method public void applyOverrideConfiguration(android.content.res.Configuration);
method protected void onApplyThemeResource(android.content.res.Resources.Theme, int, boolean);
+ method public void setTheme(@Nullable android.content.res.Resources.Theme);
}
public final class Display {
diff --git a/api/system-current.txt b/api/system-current.txt
index 33b1586..50a2553 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3409,13 +3409,13 @@
public final class AudioFocusInfo implements android.os.Parcelable {
method public int describeContents();
- method public android.media.AudioAttributes getAttributes();
- method public String getClientId();
+ method @NonNull public android.media.AudioAttributes getAttributes();
+ method @NonNull public String getClientId();
method public int getClientUid();
method public int getFlags();
method public int getGainRequest();
method public int getLossReceived();
- method public String getPackageName();
+ method @NonNull public String getPackageName();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.media.AudioFocusInfo> CREATOR;
}
diff --git a/api/test-current.txt b/api/test-current.txt
index d91ad44..16098c1 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2748,7 +2748,15 @@
public final class ContentCaptureManager {
method public boolean isContentCaptureFeatureEnabled();
method public void setContentCaptureFeatureEnabled(boolean);
+ field public static final String DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY = "idle_flush_frequency";
+ field public static final String DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL = "logging_level";
+ field public static final String DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE = "log_history_size";
+ field public static final String DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE = "max_buffer_size";
field public static final String DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED = "service_explicitly_enabled";
+ field public static final String DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY = "text_change_flush_frequency";
+ field public static final int LOGGING_LEVEL_DEBUG = 1; // 0x1
+ field public static final int LOGGING_LEVEL_OFF = 0; // 0x0
+ field public static final int LOGGING_LEVEL_VERBOSE = 2; // 0x2
}
public final class ViewNode extends android.app.assist.AssistStructure.ViewNode {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 5f778da..e55c964 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -71,6 +71,7 @@
import android.os.Looper;
import android.os.Parcelable;
import android.os.PersistableBundle;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.StrictMode;
@@ -2297,7 +2298,7 @@
public final void requestShowKeyboardShortcuts() {
Intent intent = new Intent(Intent.ACTION_SHOW_KEYBOARD_SHORTCUTS);
intent.setPackage(KEYBOARD_SHORTCUTS_RECEIVER_PKG_NAME);
- sendBroadcastAsUser(intent, UserHandle.SYSTEM);
+ sendBroadcastAsUser(intent, Process.myUserHandle());
}
/**
@@ -2306,7 +2307,7 @@
public final void dismissKeyboardShortcutsHelper() {
Intent intent = new Intent(Intent.ACTION_DISMISS_KEYBOARD_SHORTCUTS);
intent.setPackage(KEYBOARD_SHORTCUTS_RECEIVER_PKG_NAME);
- sendBroadcastAsUser(intent, UserHandle.SYSTEM);
+ sendBroadcastAsUser(intent, Process.myUserHandle());
}
@Override
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 87bf5ed..f116e13 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -27,6 +27,7 @@
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
+import android.content.pm.ServiceInfo.ForegroundServiceType;
import android.content.res.Configuration;
import android.os.Build;
import android.os.IBinder;
@@ -735,7 +736,7 @@
* @see {@link android.content.pm.ServiceInfo} for the set of FOREGROUND_SERVICE_TYPE flags.
*/
public final void startForeground(int id, @NonNull Notification notification,
- int foregroundServiceType) {
+ @ForegroundServiceType int foregroundServiceType) {
try {
mActivityManager.setServiceForeground(
new ComponentName(this, mClassName), mToken, id,
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index b9f56b1..c12a92f 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1129,7 +1129,11 @@
IBinder b = ServiceManager
.getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);
IContentCaptureManager service = IContentCaptureManager.Stub.asInterface(b);
- return new ContentCaptureManager(outerContext, service);
+ if (service != null) {
+ // When feature is disabled, we return a null manager to apps so the
+ // performance impact is practically zero
+ return new ContentCaptureManager(outerContext, service);
+ }
}
return null;
}});
diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java
index 94a2a3e..97efa01 100644
--- a/core/java/android/app/usage/UsageStats.java
+++ b/core/java/android/app/usage/UsageStats.java
@@ -465,8 +465,6 @@
mActivities.put(instanceId, eventType);
break;
case ACTIVITY_STOPPED:
- mActivities.put(instanceId, eventType);
- break;
case ACTIVITY_DESTROYED:
// remove activity from the map.
mActivities.delete(instanceId);
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index 60475de..4a2f800 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -151,6 +151,7 @@
* @hide
*/
@IntDef(flag = true, prefix = { "FOREGROUND_SERVICE_TYPE_" }, value = {
+ FOREGROUND_SERVICE_TYPE_MANIFEST,
FOREGROUND_SERVICE_TYPE_NONE,
FOREGROUND_SERVICE_TYPE_DATA_SYNC,
FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK,
@@ -180,10 +181,10 @@
}
/**
- * Return the current foreground service type.
- * @return the current foreground service type.
+ * Return foreground service type specified in the manifest..
+ * @return foreground service type specified in the manifest.
*/
- public int getForegroundServiceType() {
+ public @ForegroundServiceType int getForegroundServiceType() {
return mForegroundServiceType;
}
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index c77500a..696e048 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.Nullable;
import android.annotation.StyleRes;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -23,6 +24,7 @@
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.os.Build;
/**
* A context wrapper that allows you to modify or replace the theme of the
@@ -31,7 +33,7 @@
public class ContextThemeWrapper extends ContextWrapper {
@UnsupportedAppUsage
private int mThemeResource;
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768723)
private Resources.Theme mTheme;
@UnsupportedAppUsage
private LayoutInflater mInflater;
@@ -146,6 +148,15 @@
}
}
+ /**
+ * Set the configure the current theme. If null is provided then the default Theme is returned
+ * on the next call to {@link #getTheme()}
+ * @param theme Theme to consume in the wrapper, a value of null resets the theme to the default
+ */
+ public void setTheme(@Nullable Resources.Theme theme) {
+ mTheme = theme;
+ }
+
/** @hide */
@Override
@UnsupportedAppUsage
diff --git a/core/java/android/view/contentcapture/ContentCaptureHelper.java b/core/java/android/view/contentcapture/ContentCaptureHelper.java
index 508880f..1cf27fc 100644
--- a/core/java/android/view/contentcapture/ContentCaptureHelper.java
+++ b/core/java/android/view/contentcapture/ContentCaptureHelper.java
@@ -15,16 +15,29 @@
*/
package android.view.contentcapture;
+import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL;
+import static android.view.contentcapture.ContentCaptureManager.LOGGING_LEVEL_DEBUG;
+import static android.view.contentcapture.ContentCaptureManager.LOGGING_LEVEL_OFF;
+import static android.view.contentcapture.ContentCaptureManager.LOGGING_LEVEL_VERBOSE;
+
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Build;
+import android.provider.DeviceConfig;
+import android.util.Log;
+import android.view.contentcapture.ContentCaptureManager.LoggingLevel;
/**
- * Helpe class for this package.
+ * Helper class for this package and server's.
+ *
+ * @hide
*/
-final class ContentCaptureHelper {
+public final class ContentCaptureHelper {
- // TODO(b/121044306): define a way to dynamically set them(for example, using settings?)
- static final boolean VERBOSE = false;
- static final boolean DEBUG = true; // STOPSHIP if not set to false
+ private static final String TAG = ContentCaptureHelper.class.getSimpleName();
+
+ public static boolean sVerbose = false;
+ public static boolean sDebug = true;
/**
* Used to log text that could contain PII.
@@ -34,6 +47,61 @@
return text == null ? null : text.length() + "_chars";
}
+ /**
+ * Gets the value of a device config property from the Content Capture namespace.
+ */
+ public static int getIntDeviceConfigProperty(@NonNull String key, int defaultValue) {
+ final String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONTENT_CAPTURE, key);
+ if (value == null) return defaultValue;
+
+ try {
+ return Integer.parseInt(value);
+ } catch (Exception e) {
+ Log.w(TAG, "error parsing value (" + value + ") of property " + key + ": " + e);
+ return defaultValue;
+ }
+ }
+
+ /**
+ * Sets the value of the static logging level constants based on device config.
+ */
+ public static void setLoggingLevel() {
+ final int defaultLevel = Build.IS_DEBUGGABLE ? LOGGING_LEVEL_DEBUG : LOGGING_LEVEL_OFF;
+ final int level = getIntDeviceConfigProperty(DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL,
+ defaultLevel);
+ Log.i(TAG, "Setting logging level to " + getLoggingLevelAsString(level));
+ sVerbose = sDebug = false;
+ switch (level) {
+ case LOGGING_LEVEL_VERBOSE:
+ sVerbose = true;
+ // fall through
+ case LOGGING_LEVEL_DEBUG:
+ sDebug = true;
+ return;
+ case LOGGING_LEVEL_OFF:
+ // You log nothing, Jon Snow!
+ return;
+ default:
+ Log.w(TAG, "setLoggingLevel(): invalud level: " + level);
+ }
+ }
+
+ /**
+ * Gets a user-friendly value for a content capture logging level.
+ */
+ public static String getLoggingLevelAsString(@LoggingLevel int level) {
+ switch (level) {
+ case LOGGING_LEVEL_OFF:
+ return "OFF";
+ case LOGGING_LEVEL_DEBUG:
+ return "DEBUG";
+ case LOGGING_LEVEL_VERBOSE:
+ return "VERBOSE";
+ default:
+ return "UNKNOWN-" + level;
+ }
+ }
+
private ContentCaptureHelper() {
throw new UnsupportedOperationException("contains only static methods");
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 634443d..9906308 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -15,9 +15,10 @@
*/
package android.view.contentcapture;
-import static android.view.contentcapture.ContentCaptureHelper.DEBUG;
-import static android.view.contentcapture.ContentCaptureHelper.VERBOSE;
+import static android.view.contentcapture.ContentCaptureHelper.sDebug;
+import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -38,16 +39,11 @@
import com.android.internal.util.SyncResultReceiver;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
-/*
- * NOTE: all methods in this class should return right away, or do the real work in a handler
- * thread.
- *
- * Hence, the only field that must be thread-safe is mEnabled, which is called at the beginning
- * of every method.
- */
/**
- * TODO(b/123577059): add javadocs / implement
+ * TODO(b/123577059): add javadocs / mention it can be null
*/
@SystemService(Context.CONTENT_CAPTURE_MANAGER_SERVICE)
public final class ContentCaptureManager {
@@ -85,12 +81,81 @@
public static final String DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED =
"service_explicitly_enabled";
+ /**
+ * Maximum number of events that are buffered before sent to the app.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE = "max_buffer_size";
+
+ /**
+ * Frequency (in ms) of buffer flushes when no events are received.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY = "idle_flush_frequency";
+
+ /**
+ * Frequency (in ms) of buffer flushes when no events are received and the last one was a
+ * text change event.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY =
+ "text_change_flush_frequency";
+
+ /**
+ * Size of events that are logging on {@code dump}.
+ *
+ * <p>Set it to {@code 0} or less to disable history.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE = "log_history_size";
+
+ /**
+ * Sets the logging level for {@code logcat} statements.
+ *
+ * <p>Valid values are: {@link #LOGGING_LEVEL_OFF}, {@value #LOGGING_LEVEL_DEBUG}, and
+ * {@link #LOGGING_LEVEL_VERBOSE}.
+ *
+ * @hide
+ */
+ @TestApi
+ public static final String DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL = "logging_level";
+
+
+ /** @hide */
+ @TestApi
+ public static final int LOGGING_LEVEL_OFF = 0;
+
+ /** @hide */
+ @TestApi
+ public static final int LOGGING_LEVEL_DEBUG = 1;
+
+ /** @hide */
+ @TestApi
+ public static final int LOGGING_LEVEL_VERBOSE = 2;
+
+ /** @hide */
+ @IntDef(flag = false, value = {
+ LOGGING_LEVEL_OFF,
+ LOGGING_LEVEL_DEBUG,
+ LOGGING_LEVEL_VERBOSE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface LoggingLevel {}
+
private final Object mLock = new Object();
@NonNull
private final Context mContext;
- @Nullable
+ @NonNull
private final IContentCaptureManager mService;
// Flags used for starting session.
@@ -107,11 +172,17 @@
/** @hide */
public ContentCaptureManager(@NonNull Context context,
- @Nullable IContentCaptureManager service) {
+ @NonNull IContentCaptureManager service) {
mContext = Preconditions.checkNotNull(context, "context cannot be null");
- if (VERBOSE) Log.v(TAG, "Constructor for " + context.getPackageName());
+ mService = Preconditions.checkNotNull(service, "service cannot be null");
- mService = service;
+ // TODO(b/123096662): right now we're reading the device config values here, but ideally
+ // it should be read on ContentCaptureManagerService and passed back when the activity
+ // started.
+ ContentCaptureHelper.setLoggingLevel();
+
+ if (sVerbose) Log.v(TAG, "Constructor for " + context.getPackageName());
+
// TODO(b/119220549): we might not even need a handler, as the IPCs are oneway. But if we
// do, then we should optimize it to run the tests after the Choreographer finishes the most
// important steps of the frame.
@@ -133,7 +204,7 @@
synchronized (mLock) {
if (mMainSession == null) {
mMainSession = new MainContentCaptureSession(mContext, this, mHandler, mService);
- if (VERBOSE) Log.v(TAG, "getMainContentCaptureSession(): created " + mMainSession);
+ if (sVerbose) Log.v(TAG, "getMainContentCaptureSession(): created " + mMainSession);
}
return mMainSession;
}
@@ -199,8 +270,6 @@
* </ul>
*/
public boolean isContentCaptureEnabled() {
- if (mService == null) return false;
-
final MainContentCaptureSession mainSession;
synchronized (mLock) {
mainSession = mMainSession;
@@ -219,7 +288,7 @@
* it on {@link android.app.Activity#onCreate(android.os.Bundle, android.os.PersistableBundle)}.
*/
public void setContentCaptureEnabled(boolean enabled) {
- if (DEBUG) {
+ if (sDebug) {
Log.d(TAG, "setContentCaptureEnabled(): setting to " + enabled + " for " + mContext);
}
@@ -242,8 +311,6 @@
@SystemApi
@TestApi
public boolean isContentCaptureFeatureEnabled() {
- if (mService == null) return false;
-
final SyncResultReceiver resultReceiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
final int resultCode;
try {
@@ -275,7 +342,7 @@
@SystemApi
@TestApi
public void setContentCaptureFeatureEnabled(boolean enabled) {
- if (DEBUG) Log.d(TAG, "setContentCaptureFeatureEnabled(): setting to " + enabled);
+ if (sDebug) Log.d(TAG, "setContentCaptureFeatureEnabled(): setting to " + enabled);
final SyncResultReceiver resultReceiver = new SyncResultReceiver(SYNC_CALLS_TIMEOUT_MS);
final int resultCode;
@@ -314,22 +381,23 @@
/** @hide */
public void dump(String prefix, PrintWriter pw) {
+ pw.print(prefix); pw.println("ContentCaptureManager");
+ final String prefix2 = prefix + " ";
synchronized (mLock) {
- pw.print(prefix); pw.println("ContentCaptureManager");
- pw.print(prefix); pw.print("isContentCaptureEnabled(): ");
+ pw.print(prefix2); pw.print("isContentCaptureEnabled(): ");
pw.println(isContentCaptureEnabled());
+ pw.print(prefix); pw.print("Debug: "); pw.print(sDebug);
+ pw.print(" Verbose: "); pw.println(sVerbose);
pw.print(prefix); pw.print("Context: "); pw.println(mContext);
pw.print(prefix); pw.print("User: "); pw.println(mContext.getUserId());
- if (mService != null) {
- pw.print(prefix); pw.print("Service: "); pw.println(mService);
- }
+ pw.print(prefix); pw.print("Service: "); pw.println(mService);
pw.print(prefix); pw.print("Flags: "); pw.println(mFlags);
if (mMainSession != null) {
- final String prefix2 = prefix + " ";
- pw.print(prefix); pw.println("Main session:");
- mMainSession.dump(prefix2, pw);
+ final String prefix3 = prefix2 + " ";
+ pw.print(prefix2); pw.println("Main session:");
+ mMainSession.dump(prefix3, pw);
} else {
- pw.print(prefix); pw.println("No sessions");
+ pw.print(prefix2); pw.println("No sessions");
}
}
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index b8d3fa6..ec3b44a 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -15,8 +15,8 @@
*/
package android.view.contentcapture;
-import static android.view.contentcapture.ContentCaptureHelper.DEBUG;
-import static android.view.contentcapture.ContentCaptureHelper.VERBOSE;
+import static android.view.contentcapture.ContentCaptureHelper.sDebug;
+import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
import android.annotation.CallSuper;
import android.annotation.IntDef;
@@ -233,7 +233,7 @@
public final ContentCaptureSession createContentCaptureSession(
@NonNull ContentCaptureContext context) {
final ContentCaptureSession child = newChild(context);
- if (DEBUG) {
+ if (sDebug) {
Log.d(TAG, "createContentCaptureSession(" + context + ": parent=" + mId + ", child="
+ child.mId);
}
@@ -285,20 +285,20 @@
public final void destroy() {
synchronized (mLock) {
if (mDestroyed) {
- if (DEBUG) Log.d(TAG, "destroy(" + mId + "): already destroyed");
+ if (sDebug) Log.d(TAG, "destroy(" + mId + "): already destroyed");
return;
}
mDestroyed = true;
// TODO(b/111276913): check state (for example, how to handle if it's waiting for remote
// id) and send it to the cache of batched commands
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "destroy(): state=" + getStateAsString(mState) + ", mId=" + mId);
}
// Finish children first
if (mChildren != null) {
final int numberChildren = mChildren.size();
- if (VERBOSE) Log.v(TAG, "Destroying " + numberChildren + " children first");
+ if (sVerbose) Log.v(TAG, "Destroying " + numberChildren + " children first");
for (int i = 0; i < numberChildren; i++) {
final ContentCaptureSession child = mChildren.get(i);
try {
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index d949f45..f4021b1 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -23,9 +23,13 @@
import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_APPEARED;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
-import static android.view.contentcapture.ContentCaptureHelper.DEBUG;
-import static android.view.contentcapture.ContentCaptureHelper.VERBOSE;
+import static android.view.contentcapture.ContentCaptureHelper.getIntDeviceConfigProperty;
import static android.view.contentcapture.ContentCaptureHelper.getSanitizedString;
+import static android.view.contentcapture.ContentCaptureHelper.sDebug;
+import static android.view.contentcapture.ContentCaptureHelper.sVerbose;
+import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY;
+import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE;
+import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -64,6 +68,7 @@
private static final String TAG = MainContentCaptureSession.class.getSimpleName();
+ // For readability purposes...
private static final boolean FORCE_FLUSH = true;
/**
@@ -71,17 +76,9 @@
*/
private static final int MSG_FLUSH = 1;
- /**
- * Maximum number of events that are buffered before sent to the app.
- */
- // TODO(b/121044064): use settings
- private static final int MAX_BUFFER_SIZE = 100;
-
- /**
- * Frequency the buffer is flushed if stale.
- */
- // TODO(b/121044064): use settings
- private static final int FLUSHING_FREQUENCY_MS = 5_000;
+ private static final int DEFAULT_MAX_BUFFER_SIZE = 100;
+ private static final int DEFAULT_FLUSHING_FREQUENCY_MS = 5_000;
+ private static final int DEFAULT_LOG_HISTORY_SIZE = 10;
/**
* Name of the {@link IResultReceiver} extra used to pass the binder interface to the service.
@@ -105,14 +102,14 @@
* Interface to the system_server binder object - it's only used to start the session (and
* notify when the session is finished).
*/
- @Nullable // TODO(b/122959591): shoul never be null, we should make main session null instead
+ @NonNull
private final IContentCaptureManager mSystemServerInterface;
/**
* Direct interface to the service binder object - it's used to send the events, including the
* last ones (when the session is finished)
*/
- @Nullable
+ @NonNull
private IContentCaptureDirectManager mDirectServiceInterface;
@Nullable
private DeathRecipient mDirectServiceVulture;
@@ -131,20 +128,42 @@
@Nullable
private ArrayList<ContentCaptureEvent> mEvents;
+ /**
+ * Maximum number of events that are buffered before sent to the app.
+ */
+ private final int mMaxBufferSize;
+
+ /**
+ * Frequency the buffer is flushed if idle.
+ */
+ private final int mIdleFlushingFrequencyMs;
+
// Used just for debugging purposes (on dump)
private long mNextFlush;
- // TODO(b/121044064): use settings to set size
- private final LocalLog mFlushHistory = new LocalLog(10);
+ @Nullable
+ private final LocalLog mFlushHistory;
/** @hide */
protected MainContentCaptureSession(@NonNull Context context,
@NonNull ContentCaptureManager manager, @NonNull Handler handler,
- @Nullable IContentCaptureManager systemServerInterface) {
+ @NonNull IContentCaptureManager systemServerInterface) {
mContext = context;
mManager = manager;
mHandler = handler;
mSystemServerInterface = systemServerInterface;
+
+ // TODO(b/123096662): right now we're reading the device config values here, but ideally
+ // it should be read on ContentCaptureManagerService and passed back when the activity
+ // started.
+ mMaxBufferSize = getIntDeviceConfigProperty(DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE,
+ DEFAULT_MAX_BUFFER_SIZE);
+ mIdleFlushingFrequencyMs = getIntDeviceConfigProperty(
+ DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY, DEFAULT_FLUSHING_FREQUENCY_MS);
+ final int logHistorySize = getIntDeviceConfigProperty(
+ DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE, DEFAULT_LOG_HISTORY_SIZE);
+
+ mFlushHistory = logHistorySize > 0 ? new LocalLog(logHistorySize) : null;
}
@Override
@@ -169,14 +188,14 @@
int flags) {
if (!isContentCaptureEnabled()) return;
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "start(): token=" + token + ", comp="
+ ComponentName.flattenToShortString(component));
}
if (hasStarted()) {
// TODO(b/122959591): make sure this is expected (and when), or use Log.w
- if (DEBUG) {
+ if (sDebug) {
Log.d(TAG, "ignoring handleStartSession(" + token + "/"
+ ComponentName.flattenToShortString(component) + " while on state "
+ getStateAsString(mState));
@@ -187,14 +206,12 @@
mApplicationToken = token;
mComponentName = component;
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "handleStartSession(): token=" + token + ", act="
+ getDebugState() + ", id=" + mId);
}
try {
- if (mSystemServerInterface == null) return;
-
mSystemServerInterface.startSession(mApplicationToken, component, mId, flags,
new IResultReceiver.Stub() {
@Override
@@ -254,7 +271,7 @@
mState = resultCode;
mDisabled.set(false);
}
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "handleSessionStarted() result: id=" + mId + " resultCode=" + resultCode
+ ", state=" + getStateAsString(mState) + ", disabled=" + mDisabled.get()
+ ", binder=" + binder + ", events=" + (mEvents == null ? 0 : mEvents.size()));
@@ -269,7 +286,7 @@
@UiThread
private void sendEvent(@NonNull ContentCaptureEvent event, boolean forceFlush) {
final int eventType = event.getType();
- if (VERBOSE) Log.v(TAG, "handleSendEvent(" + getDebugState() + "): " + event);
+ if (sVerbose) Log.v(TAG, "handleSendEvent(" + getDebugState() + "): " + event);
if (!hasStarted() && eventType != ContentCaptureEvent.TYPE_SESSION_STARTED
&& eventType != ContentCaptureEvent.TYPE_CONTEXT_UPDATED) {
// TODO(b/120494182): comment when this could happen (dialogs?)
@@ -282,14 +299,14 @@
// This happens when the event was queued in the handler before the sesison was ready,
// then handleSessionStarted() returned and set it as disabled - we need to drop it,
// otherwise it will keep triggering handleScheduleFlush()
- if (VERBOSE) Log.v(TAG, "handleSendEvent(): ignoring when disabled");
+ if (sVerbose) Log.v(TAG, "handleSendEvent(): ignoring when disabled");
return;
}
if (mEvents == null) {
- if (VERBOSE) {
- Log.v(TAG, "handleSendEvent(): creating buffer for " + MAX_BUFFER_SIZE + " events");
+ if (sVerbose) {
+ Log.v(TAG, "handleSendEvent(): creating buffer for " + mMaxBufferSize + " events");
}
- mEvents = new ArrayList<>(MAX_BUFFER_SIZE);
+ mEvents = new ArrayList<>(mMaxBufferSize);
}
// Some type of events can be merged together
@@ -301,7 +318,7 @@
// TODO(b/121045053): check if flags match
if (lastEvent.getType() == TYPE_VIEW_TEXT_CHANGED
&& lastEvent.getId().equals(event.getId())) {
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "Buffering VIEW_TEXT_CHANGED event, updated text="
+ getSanitizedString(event.getText()));
}
@@ -315,7 +332,7 @@
final ContentCaptureEvent lastEvent = mEvents.get(mEvents.size() - 1);
if (lastEvent.getType() == TYPE_VIEW_DISAPPEARED
&& event.getSessionId().equals(lastEvent.getSessionId())) {
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "Buffering TYPE_VIEW_DISAPPEARED events for session "
+ lastEvent.getSessionId());
}
@@ -330,20 +347,20 @@
final int numberEvents = mEvents.size();
- final boolean bufferEvent = numberEvents < MAX_BUFFER_SIZE;
+ final boolean bufferEvent = numberEvents < mMaxBufferSize;
if (bufferEvent && !forceFlush) {
scheduleFlush(FLUSH_REASON_IDLE_TIMEOUT, /* checkExisting= */ true);
return;
}
- if (mState != STATE_ACTIVE && numberEvents >= MAX_BUFFER_SIZE) {
+ if (mState != STATE_ACTIVE && numberEvents >= mMaxBufferSize) {
// Callback from startSession hasn't been called yet - typically happens on system
// apps that are started before the system service
// TODO(b/122959591): try to ignore session while system is not ready / boot
// not complete instead. Similarly, the manager service should return right away
// when the user does not have a service set
- if (DEBUG) {
+ if (sDebug) {
Log.d(TAG, "Closing session for " + getDebugState()
+ " after " + numberEvents + " delayed events");
}
@@ -398,12 +415,12 @@
@UiThread
private void scheduleFlush(@FlushReason int reason, boolean checkExisting) {
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "handleScheduleFlush(" + getDebugState(reason)
+ ", checkExisting=" + checkExisting);
}
if (!hasStarted()) {
- if (VERBOSE) Log.v(TAG, "handleScheduleFlush(): session not started yet");
+ if (sVerbose) Log.v(TAG, "handleScheduleFlush(): session not started yet");
return;
}
@@ -418,19 +435,19 @@
// "Renew" the flush message by removing the previous one
mHandler.removeMessages(MSG_FLUSH);
}
- mNextFlush = System.currentTimeMillis() + FLUSHING_FREQUENCY_MS;
- if (VERBOSE) {
+ mNextFlush = System.currentTimeMillis() + mIdleFlushingFrequencyMs;
+ if (sVerbose) {
Log.v(TAG, "handleScheduleFlush(): scheduled to flush in "
- + FLUSHING_FREQUENCY_MS + "ms: " + TimeUtils.logTimeOfDay(mNextFlush));
+ + mIdleFlushingFrequencyMs + "ms: " + TimeUtils.logTimeOfDay(mNextFlush));
}
// Post using a Runnable directly to trim a few μs from PooledLambda.obtainMessage()
- mHandler.postDelayed(() -> flushIfNeeded(reason), MSG_FLUSH, FLUSHING_FREQUENCY_MS);
+ mHandler.postDelayed(() -> flushIfNeeded(reason), MSG_FLUSH, mIdleFlushingFrequencyMs);
}
@UiThread
private void flushIfNeeded(@FlushReason int reason) {
if (mEvents == null || mEvents.isEmpty()) {
- if (VERBOSE) Log.v(TAG, "Nothing to flush");
+ if (sVerbose) Log.v(TAG, "Nothing to flush");
return;
}
flush(reason);
@@ -448,7 +465,7 @@
}
if (mDirectServiceInterface == null) {
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "handleForceFlush(" + getDebugState(reason) + "): hold your horses, "
+ "client not ready: " + mEvents);
}
@@ -460,14 +477,16 @@
final int numberEvents = mEvents.size();
final String reasonString = getflushReasonAsString(reason);
- if (DEBUG) {
+ if (sDebug) {
Log.d(TAG, "Flushing " + numberEvents + " event(s) for " + getDebugState(reason));
}
- // Logs reason, size, max size, idle timeout
- final String logRecord = "r=" + reasonString + " s=" + numberEvents
- + " m=" + MAX_BUFFER_SIZE + " i=" + FLUSHING_FREQUENCY_MS;
- try {
+ if (mFlushHistory != null) {
+ // Logs reason, size, max size, idle timeout
+ final String logRecord = "r=" + reasonString + " s=" + numberEvents
+ + " m=" + mMaxBufferSize + " i=" + mIdleFlushingFrequencyMs;
mFlushHistory.log(logRecord);
+ }
+ try {
mHandler.removeMessages(MSG_FLUSH);
final ParceledListSlice<ContentCaptureEvent> events = clearEvents();
@@ -500,15 +519,13 @@
@UiThread
private void destroySession() {
- if (DEBUG) {
+ if (sDebug) {
Log.d(TAG, "Destroying session (ctx=" + mContext + ", id=" + mId + ") with "
+ (mEvents == null ? 0 : mEvents.size()) + " event(s) for "
+ getDebugState());
}
try {
- if (mSystemServerInterface == null) return;
-
mSystemServerInterface.finishSession(mId);
} catch (RemoteException e) {
Log.e(TAG, "Error destroying system-service session " + mId + " for "
@@ -520,7 +537,7 @@
// clearings out.
@UiThread
private void resetSession(int newState) {
- if (VERBOSE) {
+ if (sVerbose) {
Log.v(TAG, "handleResetSession(" + getActivityName() + "): from "
+ getStateAsString(mState) + " to " + getStateAsString(newState));
}
@@ -628,12 +645,11 @@
@Override
void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
+ super.dump(prefix, pw);
+
pw.print(prefix); pw.print("mContext: "); pw.println(mContext);
pw.print(prefix); pw.print("user: "); pw.println(mContext.getUserId());
- if (mSystemServerInterface != null) {
- pw.print(prefix); pw.print("mSystemServerInterface: ");
- pw.println(mSystemServerInterface);
- }
+ pw.print(prefix); pw.print("mSystemServerInterface: ");
if (mDirectServiceInterface != null) {
pw.print(prefix); pw.print("mDirectServiceInterface: ");
pw.println(mDirectServiceInterface);
@@ -651,8 +667,8 @@
if (mEvents != null && !mEvents.isEmpty()) {
final int numberEvents = mEvents.size();
pw.print(prefix); pw.print("buffered events: "); pw.print(numberEvents);
- pw.print('/'); pw.println(MAX_BUFFER_SIZE);
- if (VERBOSE && numberEvents > 0) {
+ pw.print('/'); pw.println(mMaxBufferSize);
+ if (sVerbose && numberEvents > 0) {
final String prefix3 = prefix + " ";
for (int i = 0; i < numberEvents; i++) {
final ContentCaptureEvent event = mEvents.get(i);
@@ -660,13 +676,17 @@
pw.println();
}
}
- pw.print(prefix); pw.print("flush frequency: "); pw.println(FLUSHING_FREQUENCY_MS);
+ pw.print(prefix); pw.print("flush frequency: "); pw.println(mIdleFlushingFrequencyMs);
pw.print(prefix); pw.print("next flush: ");
TimeUtils.formatDuration(mNextFlush - System.currentTimeMillis(), pw);
pw.print(" ("); pw.print(TimeUtils.logTimeOfDay(mNextFlush)); pw.println(")");
}
- pw.print(prefix); pw.println("flush history:");
- mFlushHistory.reverseDump(/* fd= */ null, pw, /* args= */ null); pw.println();
+ if (mFlushHistory != null) {
+ pw.print(prefix); pw.println("flush history:");
+ mFlushHistory.reverseDump(/* fd= */ null, pw, /* args= */ null); pw.println();
+ } else {
+ pw.print(prefix); pw.println("not logging flush history");
+ }
super.dump(prefix, pw);
}
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index af0b7c3..7406136 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -230,6 +230,7 @@
],
static_libs: [
+ "libasync_safe",
"libgif",
"libseccomp_policy",
"libgrallocusage",
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index fe81347..7b4e4ea 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -25,6 +25,8 @@
#define LOG_TAG "Zygote"
+#include <async_safe/log.h>
+
// sys/mount.h has to come before linux/fs.h due to redefinition of MS_RDONLY, MS_BIND, etc
#include <sys/mount.h>
#include <linux/fs.h>
@@ -303,27 +305,23 @@
int saved_errno = errno;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
- // Log process-death status that we care about. In general it is
- // not safe to call LOG(...) from a signal handler because of
- // possible reentrancy. However, we know a priori that the
- // current implementation of LOG() is safe to call from a SIGCHLD
- // handler in the zygote process. If the LOG() implementation
- // changes its locking strategy or its use of syscalls within the
- // lazy-init critical section, its use here may become unsafe.
+ // Log process-death status that we care about.
if (WIFEXITED(status)) {
- ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
+ async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG,
+ "Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
- ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status));
- if (WCOREDUMP(status)) {
- ALOGI("Process %d dumped core.", pid);
- }
+ async_safe_format_log(ANDROID_LOG_INFO, LOG_TAG,
+ "Process %d exited due to signal %d (%s)%s", pid,
+ WTERMSIG(status), strsignal(WTERMSIG(status)),
+ WCOREDUMP(status) ? "; core dumped" : "");
}
// If the just-crashed process is the system_server, bring down zygote
// so that it is restarted by init and system server will be restarted
// from there.
if (pid == gSystemServerPid) {
- ALOGE("Exit zygote because system server (%d) has terminated", pid);
+ async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+ "Exit zygote because system server (pid %d) has terminated", pid);
kill(getpid(), SIGKILL);
}
@@ -336,14 +334,17 @@
// Note that we shouldn't consider ECHILD an error because
// the secondary zygote might have no children left to wait for.
if (pid < 0 && errno != ECHILD) {
- ALOGW("Zygote SIGCHLD error in waitpid: %s", strerror(errno));
+ async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG,
+ "Zygote SIGCHLD error in waitpid: %s", strerror(errno));
}
if (blastulas_removed > 0) {
if (write(gBlastulaPoolEventFD, &blastulas_removed, sizeof(blastulas_removed)) == -1) {
// If this write fails something went terribly wrong. We will now kill
// the zygote and let the system bring it back up.
- ALOGE("Zygote failed to write to blastula pool event FD: %s", strerror(errno));
+ async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+ "Zygote failed to write to blastula pool event FD: %s",
+ strerror(errno));
kill(getpid(), SIGKILL);
}
}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 8dfd5e84..e65e7da 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -869,6 +869,9 @@
which means to get a larger screen. -->
<bool name="config_lidControlsDisplayFold">false</bool>
+ <!-- Indicate the display area rect for foldable devices in folded state. -->
+ <string name="config_foldedArea"></string>
+
<!-- Desk dock behavior -->
<!-- The number of degrees to rotate the display when the device is in a desk dock.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 16aed90..7ef5e02 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3586,7 +3586,10 @@
<java-symbol type="integer" name="config_defaultRingVibrationIntensity" />
<java-symbol type="bool" name="config_maskMainBuiltInDisplayCutout" />
+
+ <!-- For Foldables -->
<java-symbol type="bool" name="config_lidControlsDisplayFold" />
+ <java-symbol type="string" name="config_foldedArea" />
<java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" />
<java-symbol type="array" name="config_disableApkUnlessMatchedSku_skus_list" />
diff --git a/media/java/android/media/AudioFocusInfo.java b/media/java/android/media/AudioFocusInfo.java
index 0a9ca02..3594ee7 100644
--- a/media/java/android/media/AudioFocusInfo.java
+++ b/media/java/android/media/AudioFocusInfo.java
@@ -16,6 +16,7 @@
package android.media;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -29,10 +30,10 @@
@SystemApi
public final class AudioFocusInfo implements Parcelable {
- private final AudioAttributes mAttributes;
+ private final @NonNull AudioAttributes mAttributes;
private final int mClientUid;
- private final String mClientId;
- private final String mPackageName;
+ private final @NonNull String mClientId;
+ private final @NonNull String mPackageName;
private final int mSdkTarget;
private int mGainRequest;
private int mLossReceived;
@@ -80,13 +81,21 @@
* The audio attributes for the audio focus request.
* @return non-null {@link AudioAttributes}.
*/
- public AudioAttributes getAttributes() { return mAttributes; }
+ public @NonNull AudioAttributes getAttributes() {
+ return mAttributes;
+ }
- public int getClientUid() { return mClientUid; }
+ public int getClientUid() {
+ return mClientUid;
+ }
- public String getClientId() { return mClientId; }
+ public @NonNull String getClientId() {
+ return mClientId;
+ }
- public String getPackageName() { return mPackageName; }
+ public @NonNull String getPackageName() {
+ return mPackageName;
+ }
/**
* The type of audio focus gain request.
diff --git a/media/java/android/media/AudioFocusRequest.java b/media/java/android/media/AudioFocusRequest.java
index b9731d1..4e70501 100644
--- a/media/java/android/media/AudioFocusRequest.java
+++ b/media/java/android/media/AudioFocusRequest.java
@@ -225,9 +225,9 @@
/** @hide */
public static final String KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING = "a11y_force_ducking";
- private final OnAudioFocusChangeListener mFocusListener; // may be null
- private final Handler mListenerHandler; // may be null
- private final AudioAttributes mAttr; // never null
+ private final @Nullable OnAudioFocusChangeListener mFocusListener;
+ private final @Nullable Handler mListenerHandler;
+ private final @NonNull AudioAttributes mAttr;
private final int mFocusGain;
private final int mFlags;
diff --git a/packages/CaptivePortalLogin/Android.bp b/packages/CaptivePortalLogin/Android.bp
index 7acdfa1..a71977f 100644
--- a/packages/CaptivePortalLogin/Android.bp
+++ b/packages/CaptivePortalLogin/Android.bp
@@ -18,7 +18,7 @@
name: "CaptivePortalLogin",
srcs: ["src/**/*.java"],
sdk_version: "system_current",
- certificate: "platform",
+ certificate: "networkstack",
static_libs: [
"androidx.legacy_legacy-support-v4",
"metrics-constants-protos",
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index e15dca0..0894ee5 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -23,8 +23,8 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
- <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
<uses-permission android:name="android.permission.NETWORK_BYPASS_PRIVATE_DNS" />
+ <uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
<application android:label="@string/app_name"
android:usesCleartextTraffic="true"
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index d656593..b700bf3 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -35,11 +35,12 @@
android_app {
name: "NetworkStack",
sdk_version: "system_current",
- certificate: "platform",
+ certificate: "networkstack",
privileged: true,
static_libs: [
"NetworkStackLib"
],
+ jarjar_rules: "jarjar-rules-shared.txt",
manifest: "AndroidManifest.xml",
required: ["NetworkStackPermissionStub"],
}
\ No newline at end of file
diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml
index 860ebfb..0476712 100644
--- a/packages/NetworkStack/AndroidManifest.xml
+++ b/packages/NetworkStack/AndroidManifest.xml
@@ -24,12 +24,10 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
- <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
<!-- Signature permission defined in NetworkStackStub -->
<uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
<!-- Send latency broadcast as current user -->
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
- <uses-permission android:name="android.permission.NETWORK_STACK" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
<application
diff --git a/packages/NetworkStack/jarjar-rules-shared.txt b/packages/NetworkStack/jarjar-rules-shared.txt
new file mode 100644
index 0000000..a8c712a
--- /dev/null
+++ b/packages/NetworkStack/jarjar-rules-shared.txt
@@ -0,0 +1,19 @@
+rule com.android.internal.util.** android.net.networkstack.util.@1
+
+rule android.net.shared.Inet4AddressUtils* android.net.networkstack.shared.Inet4AddressUtils@1
+rule android.net.shared.InetAddressUtils* android.net.networkstack.shared.InetAddressUtils@1
+
+# Ignore DhcpResultsParcelable, but jarjar DhcpResults
+# TODO: move DhcpResults into services.net and delete from here
+rule android.net.DhcpResultsParcelable* @0
+rule android.net.DhcpResults* android.net.networkstack.DhcpResults@1
+rule android.net.LocalLog* android.net.networkstack.LocalLog@1
+
+# TODO: remove from framework dependencies, then remove here
+rule android.net.InterfaceConfigurationParcel* android.net.networkstack.InterfaceConfigurationParcel@1
+rule android.net.TetherStatsParcel* android.net.networkstack.TetherStatsParcel@1
+
+# Used by UidRange, which is used by framework classes such as NetworkCapabilities.
+rule android.net.UidRangeParcel* android.net.networkstack.UidRangeParcel@1
+# TODO: move TcpKeepalivePacketData to services.net and delete
+rule android.net.TcpKeepalivePacketDataParcelable* android.net.networkstack.TcpKeepalivePacketDataParcelable@1
\ No newline at end of file
diff --git a/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java b/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java
index 96d1a28..97d26c7 100644
--- a/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java
+++ b/packages/NetworkStack/src/android/net/dhcp/DhcpPacketListener.java
@@ -18,7 +18,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.net.shared.FdEventsReader;
+import android.net.util.FdEventsReader;
import android.os.Handler;
import android.system.Os;
diff --git a/core/java/android/net/shared/FdEventsReader.java b/packages/NetworkStack/src/android/net/util/FdEventsReader.java
similarity index 98%
rename from core/java/android/net/shared/FdEventsReader.java
rename to packages/NetworkStack/src/android/net/util/FdEventsReader.java
index bffbfb1..1380ea7 100644
--- a/core/java/android/net/shared/FdEventsReader.java
+++ b/packages/NetworkStack/src/android/net/util/FdEventsReader.java
@@ -14,14 +14,13 @@
* limitations under the License.
*/
-package android.net.shared;
+package android.net.util;
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.net.util.SocketUtils;
import android.os.Handler;
import android.os.Looper;
import android.os.MessageQueue;
diff --git a/packages/NetworkStack/src/android/net/util/PacketReader.java b/packages/NetworkStack/src/android/net/util/PacketReader.java
index 94b1e9f..4aec6b6 100644
--- a/packages/NetworkStack/src/android/net/util/PacketReader.java
+++ b/packages/NetworkStack/src/android/net/util/PacketReader.java
@@ -18,7 +18,6 @@
import static java.lang.Math.max;
-import android.net.shared.FdEventsReader;
import android.os.Handler;
import android.system.Os;
diff --git a/packages/NetworkStackPermissionStub/Android.bp b/packages/NetworkStackPermissionStub/Android.bp
index 94870c9..dd70cf5 100644
--- a/packages/NetworkStackPermissionStub/Android.bp
+++ b/packages/NetworkStackPermissionStub/Android.bp
@@ -21,7 +21,7 @@
// a classes.dex.
srcs: ["src/**/*.java"],
platform_apis: true,
- certificate: "platform",
+ certificate: "networkstack",
privileged: true,
manifest: "AndroidManifest.xml",
}
diff --git a/packages/SystemUI/res/drawable/privacy_chip_bg.xml b/packages/SystemUI/res/drawable/privacy_chip_bg.xml
index f1158ef..b7b21fa 100644
--- a/packages/SystemUI/res/drawable/privacy_chip_bg.xml
+++ b/packages/SystemUI/res/drawable/privacy_chip_bg.xml
@@ -16,8 +16,8 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="#4a4a4a" />
+ <solid android:color="#242424" /> <!-- 14% of white -->
<padding android:paddingTop="@dimen/ongoing_appops_chip_bg_padding"
- android:paddingBottom="@dimen/ongoing_appops_chip_bg_padding"/>
+ android:paddingBottom="@dimen/ongoing_appops_chip_bg_padding" />
<corners android:radius="@dimen/ongoing_appops_chip_bg_corner_radius" />
</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
index 58fe811..f64a64e6 100644
--- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
+
<com.android.systemui.privacy.OngoingPrivacyChip
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/privacy_chip"
@@ -22,47 +23,39 @@
android:layout_width="wrap_content"
android:layout_marginLeft="@dimen/ongoing_appops_chip_margin"
android:layout_marginRight="@dimen/ongoing_appops_chip_margin"
- android:layout_marginTop="@dimen/ongoing_appops_top_chip_margin"
- android:layout_marginBottom="@dimen/ongoing_appops_top_chip_margin"
- android:gravity="center_vertical|center_horizontal"
android:layout_gravity="center_vertical|start"
+ android:gravity="center_vertical"
android:orientation="horizontal"
- android:paddingStart="@dimen/ongoing_appops_chip_side_padding"
- android:paddingEnd="@dimen/ongoing_appops_chip_side_padding"
android:focusable="true">
- <TextView
- android:id="@+id/in_use_text"
- android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:layout_gravity="center_vertical|start"
- android:layout_marginEnd="@dimen/ongoing_appops_chip_icon_margin_collapsed"
- android:gravity="center_vertical"
- android:textAppearance="@style/TextAppearance.StatusBar.Clock"
- android:textColor="@color/status_bar_clock_color"
- android:text="@string/ongoing_privacy_chip_in_use"
- />
-
<LinearLayout
- android:id="@+id/icons_container"
- android:layout_height="match_parent"
+ android:id="@+id/background"
+ android:layout_height="@dimen/ongoing_appops_chip_height"
android:layout_width="wrap_content"
- android:layout_gravity="center_vertical"
- android:gravity="center_vertical"
- />
+ >
+ <LinearLayout
+ android:id="@+id/icons_container"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_marginStart="@dimen/ongoing_appops_chip_items_margin"
+ android:layout_gravity="center_vertical"
+ android:gravity="center_vertical"
+ />
- <TextView
- android:id="@+id/text_container"
- android:layout_height="match_parent"
- android:layout_width="wrap_content"
- android:singleLine="true"
- android:ellipsize="end"
- android:lines="1"
- android:layout_gravity="center_vertical|end"
- android:gravity="center_vertical"
- android:textAppearance="@style/TextAppearance.StatusBar.Clock"
- android:textColor="@color/status_bar_clock_color"
- android:layout_marginStart="@dimen/ongoing_appops_chip_icon_margin_collapsed"
- android:layout_marginEnd="@dimen/ongoing_appops_chip_icon_margin_collapsed"
- />
+ <TextView
+ android:id="@+id/text_container"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_gravity="center_vertical|end"
+ android:paddingStart="@dimen/ongoing_appops_chip_text_padding"
+ android:paddingEnd="@dimen/ongoing_appops_chip_text_padding"
+ android:gravity="center_vertical"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:lines="1"
+ android:textAppearance="@style/TextAppearance.StatusBar.Clock"
+ android:textSize="@dimen/ongoing_appops_chip_text_size"
+ android:textColor="@color/status_bar_clock_color"
+ />
+ </LinearLayout>
</com.android.systemui.privacy.OngoingPrivacyChip>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index df858f0..bb0c6f6 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -34,5 +34,4 @@
<bool name="quick_settings_wide">true</bool>
<dimen name="qs_detail_margin_top">0dp</dimen>
<dimen name="qs_paged_tile_layout_padding_bottom">0dp</dimen>
- <dimen name="ongoing_appops_top_chip_margin">2dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 1e1245f..1c7ee36 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -980,26 +980,32 @@
<dimen name="ongoing_appops_dialog_items_bottom_margin">24dp</dimen>
<!-- Top and bottom margin of title in Ongoing App Ops dialog -->
<dimen name="ongoing_appops_dialog_title_margin_top_bottom">18dp</dimen>
- <!-- Side margins around the Ongoing App Ops chip-->
- <dimen name="ongoing_appops_chip_margin">12dp</dimen>
- <!-- Top and bottom margins around the Ongoing App Ops chip -->
- <dimen name="ongoing_appops_top_chip_margin">12dp</dimen>
- <!-- Start and End padding for Ongoing App Ops chip -->
- <dimen name="ongoing_appops_chip_side_padding">6dp</dimen>
- <!-- Padding between background of Ongoing App Ops chip and content -->
- <dimen name="ongoing_appops_chip_bg_padding">0dp</dimen>
- <!-- Margin between icons of Ongoing App Ops chip when QQS-->
- <dimen name="ongoing_appops_chip_icon_margin_collapsed">0dp</dimen>
- <!-- Margin between icons of Ongoing App Ops chip when QS-->
- <dimen name="ongoing_appops_chip_icon_margin_expanded">8dp</dimen>
- <!-- Icon size of Ongoing App Ops chip -->
- <dimen name="ongoing_appops_chip_icon_size">18dp</dimen>
- <!-- Radius of Ongoing App Ops chip corners -->
- <dimen name="ongoing_appops_chip_bg_corner_radius">4dp</dimen>
<!-- Text size for Ongoing App Ops dialog title -->
<dimen name="ongoing_appops_dialog_title_size">20sp</dimen>
<!-- Text size for Ongoing App Ops dialog items -->
<dimen name="ongoing_appops_dialog_item_size">16sp</dimen>
+ <!-- Side margins around the Ongoing App Ops chip-->
+ <dimen name="ongoing_appops_chip_margin">0dp</dimen>
+ <!-- Height of the Ongoing App Ops chip -->
+ <dimen name="ongoing_appops_chip_height">32dp</dimen>
+ <!-- Start and End padding for Ongoing App Ops chip -->
+ <dimen name="ongoing_appops_chip_text_padding">8dp</dimen>
+ <!-- Padding between background of Ongoing App Ops chip and content -->
+ <dimen name="ongoing_appops_chip_bg_padding">0dp</dimen>
+ <!-- Side padding between background of Ongoing App Ops chip and content -->
+ <dimen name="ongoing_appops_chip_side_padding">8dp</dimen>
+ <!-- Margin between icons of Ongoing App Ops chip when QQS-->
+ <dimen name="ongoing_appops_chip_icon_margin_collapsed">0dp</dimen>
+ <!-- Margin between icons of Ongoing App Ops chip when QS-->
+ <dimen name="ongoing_appops_chip_icon_margin_expanded">2dp</dimen>
+ <!-- Icon size of Ongoing App Ops chip -->
+ <dimen name="ongoing_appops_chip_icon_size">@*android:dimen/status_bar_icon_size</dimen>
+ <!-- Radius of Ongoing App Ops chip corners -->
+ <dimen name="ongoing_appops_chip_bg_corner_radius">16dp</dimen>
+ <!-- Size of text of Ongoing App Ops chip -->
+ <dimen name="ongoing_appops_chip_text_size">12sp</dimen>
+ <!-- Margin between items in Ongoing App Ops chip -->
+ <dimen name="ongoing_appops_chip_items_margin">8dp</dimen>
<!-- How much a bubble is elevated -->
<dimen name="bubble_elevation">8dp</dimen>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f277c43..3ac7fd4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -724,6 +724,7 @@
}
private void handleFaceAuthFailed() {
+ setFaceRunningState(BIOMETRIC_STATE_STOPPED);
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 6d583df..6bb4fb5 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -41,6 +41,7 @@
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
+import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
@@ -141,7 +142,7 @@
StatusBar statusBar, StatusBarStateController statusBarStateController,
NotificationListener listener) {
return new NotificationIconAreaController(context, statusBar, statusBarStateController,
- listener);
+ listener, Dependency.get(NotificationMediaManager.class));
}
public KeyguardIndicationController createKeyguardIndicationController(Context context,
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
index 1765dc8..15dc43f 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
@@ -16,7 +16,6 @@
import android.content.Context
import android.util.AttributeSet
-import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
@@ -40,10 +39,12 @@
context.resources.getDimensionPixelSize(R.dimen.ongoing_appops_chip_icon_size)
private val iconColor = context.resources.getColor(
R.color.status_bar_clock_color, context.theme)
+ private val sidePadding =
+ context.resources.getDimensionPixelSize(R.dimen.ongoing_appops_chip_side_padding)
private val backgroundDrawable = context.getDrawable(R.drawable.privacy_chip_bg)
private lateinit var text: TextView
private lateinit var iconsContainer: LinearLayout
- private lateinit var inUseText: TextView
+ private lateinit var back: LinearLayout
var expanded = false
set(value) {
if (value != field) {
@@ -64,15 +65,15 @@
override fun onFinishInflate() {
super.onFinishInflate()
- inUseText = findViewById(R.id.in_use_text)
+ back = findViewById(R.id.background)
text = findViewById(R.id.text_container)
iconsContainer = findViewById(R.id.icons_container)
}
// Should only be called if the builder icons or app changed
private fun updateView() {
- inUseText.visibility = if (expanded) View.GONE else View.VISIBLE
- background = if (expanded) backgroundDrawable else null
+ back.background = if (expanded) backgroundDrawable else null
+ back.setPaddingRelative(0, 0, if (expanded) sidePadding else 0, 0)
fun setIcons(dialogBuilder: PrivacyDialogBuilder, iconsContainer: ViewGroup) {
iconsContainer.removeAllViews()
dialogBuilder.generateIcons().forEachIndexed { i, it ->
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index a55dacd..6a8c19a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -387,15 +387,6 @@
setLayoutParams(lp);
- if (mPrivacyChip != null) {
- MarginLayoutParams lm = (MarginLayoutParams) mPrivacyChip.getLayoutParams();
- int sideMargins = lm.leftMargin;
- int topBottomMargins = resources.getDimensionPixelSize(
- R.dimen.ongoing_appops_top_chip_margin);
- lm.setMargins(sideMargins, topBottomMargins, sideMargins, topBottomMargins);
- mPrivacyChip.setLayoutParams(lm);
- }
-
updateStatusIconAlphaAnimator();
updateHeaderTextContainerAlphaAnimator();
updatePrivacyChipAlphaAnimator();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 62f85fe..99269cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -24,6 +24,7 @@
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -47,6 +48,7 @@
private final NotificationEntryManager mEntryManager;
private final Runnable mUpdateStatusBarIcons = this::updateStatusBarIcons;
private final StatusBarStateController mStatusBarStateController;
+ private final NotificationMediaManager mMediaManager;
@VisibleForTesting
final NotificationListener.NotificationSettingsListener mSettingsListener =
new NotificationListener.NotificationSettingsListener() {
@@ -93,13 +95,15 @@
public NotificationIconAreaController(Context context, StatusBar statusBar,
StatusBarStateController statusBarStateController,
- NotificationListener notificationListener) {
+ NotificationListener notificationListener,
+ NotificationMediaManager notificationMediaManager) {
mStatusBar = statusBar;
mContrastColorUtil = ContrastColorUtil.getInstance(context);
mContext = context;
mEntryManager = Dependency.get(NotificationEntryManager.class);
mStatusBarStateController = statusBarStateController;
mStatusBarStateController.addCallback(this);
+ mMediaManager = notificationMediaManager;
notificationListener.addNotificationSettingsListener(mSettingsListener);
initializeNotificationAreaViews(context);
@@ -192,10 +196,13 @@
protected boolean shouldShowNotificationIcon(NotificationEntry entry,
boolean showAmbient, boolean showLowPriority, boolean hideDismissed,
- boolean hideRepliedMessages) {
+ boolean hideRepliedMessages, boolean hideCurrentMedia) {
if (mEntryManager.getNotificationData().isAmbient(entry.key) && !showAmbient) {
return false;
}
+ if (hideCurrentMedia && entry.key.equals(mMediaManager.getMediaNotificationKey())) {
+ return false;
+ }
if (!showLowPriority && !entry.isHighPriority()) {
return false;
}
@@ -235,14 +242,16 @@
private void updateShelfIcons() {
updateIconsForLayout(entry -> entry.expandedIcon, mShelfIcons,
true /* showAmbient */, !mFullyDark /* showLowPriority */,
- false /* hideDismissed */, mFullyDark /* hideRepliedMessages */);
+ false /* hideDismissed */, mFullyDark /* hideRepliedMessages */,
+ mFullyDark /* hideCurrentMedia */);
}
public void updateStatusBarIcons() {
updateIconsForLayout(entry -> entry.icon, mNotificationIcons,
false /* showAmbient */, mShowLowPriority /* showLowPriority */,
true /* hideDismissed */,
- true /* hideRepliedMessages */);
+ true /* hideRepliedMessages */,
+ false /* hideCurrentMedia */);
}
@VisibleForTesting
@@ -261,7 +270,7 @@
*/
private void updateIconsForLayout(Function<NotificationEntry, StatusBarIconView> function,
NotificationIconContainer hostLayout, boolean showAmbient, boolean showLowPriority,
- boolean hideDismissed, boolean hideRepliedMessages) {
+ boolean hideDismissed, boolean hideRepliedMessages, boolean hideCurrentMedia) {
ArrayList<StatusBarIconView> toShow = new ArrayList<>(
mNotificationScrollLayout.getChildCount());
@@ -271,7 +280,7 @@
if (view instanceof ExpandableNotificationRow) {
NotificationEntry ent = ((ExpandableNotificationRow) view).getEntry();
if (shouldShowNotificationIcon(ent, showAmbient, showLowPriority, hideDismissed,
- hideRepliedMessages)) {
+ hideRepliedMessages, hideCurrentMedia)) {
toShow.add(function.apply(ent));
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
index 608dd8b..120d0b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
@@ -29,6 +29,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationMediaManager;
import org.junit.Before;
import org.junit.Test;
@@ -47,6 +48,8 @@
StatusBar mStatusBar;
@Mock
StatusBarStateController mStatusBarStateController;
+ @Mock
+ private NotificationMediaManager mMediaManager;
private NotificationIconAreaController mController;
@Before
@@ -54,7 +57,7 @@
MockitoAnnotations.initMocks(this);
mController = new NotificationIconAreaController(mContext, mStatusBar,
- mStatusBarStateController, mListener);
+ mStatusBarStateController, mListener, mMediaManager);
}
@Test
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 4afbc64..4bd50ec 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -45,6 +45,7 @@
import android.util.LocalLog;
import android.util.Slog;
import android.util.SparseBooleanArray;
+import android.view.contentcapture.ContentCaptureHelper;
import android.view.contentcapture.ContentCaptureManager;
import android.view.contentcapture.IContentCaptureManager;
import android.view.contentcapture.UserDataRemovalRequest;
@@ -79,7 +80,8 @@
private final LocalService mLocalService = new LocalService();
- private final LocalLog mRequestsHistory = new LocalLog(20);
+ @Nullable
+ final LocalLog mRequestsHistory;
@GuardedBy("mLock")
private ActivityManagerInternal mAm;
@@ -105,15 +107,19 @@
UserManager.DISALLOW_CONTENT_CAPTURE);
DeviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ActivityThread.currentApplication().getMainExecutor(),
- (namespace, key, value) -> {
- if (!ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED
- .equals(key)) {
- Slog.i(mTag, "Ignoring change on " + key);
- return;
- }
- setDisabledByDeviceConfig(value);
- });
- setDisabledByDeviceConfig();
+ (namespace, key, value) -> onDeviceConfigChange(key, value));
+ setLoggingLevelFromDeviceConfig();
+ setDisabledFromDeviceConfig();
+
+ final int loggingSize = ContentCaptureHelper.getIntDeviceConfigProperty(
+ ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE, 20);
+ if (loggingSize > 0) {
+ if (debug) Slog.d(mTag, "log history size: " + loggingSize);
+ mRequestsHistory = new LocalLog(loggingSize);
+ } else {
+ if (debug) Slog.d(mTag, "disabled log history because size is " + loggingSize);
+ mRequestsHistory = null;
+ }
// Sets which services are disabled
final UserManager um = getContext().getSystemService(UserManager.class);
@@ -213,7 +219,33 @@
return false;
}
- private void setDisabledByDeviceConfig() {
+ private void onDeviceConfigChange(@NonNull String key, @Nullable String value) {
+ switch (key) {
+ case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED:
+ setDisabledByDeviceConfig(value);
+ return;
+ case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL:
+ setLoggingLevelFromDeviceConfig();
+ return;
+ case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_MAX_BUFFER_SIZE:
+ case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY:
+ case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE:
+ case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY:
+ // TODO(b/123096662): implement it
+ Slog.d(mTag, "changes on " + key + " not supported yet");
+ return;
+ default:
+ Slog.i(mTag, "Ignoring change on " + key);
+ }
+ }
+
+ private void setLoggingLevelFromDeviceConfig() {
+ ContentCaptureHelper.setLoggingLevel();
+ verbose = ContentCaptureHelper.sVerbose;
+ debug = ContentCaptureHelper.sDebug;
+ }
+
+ private void setDisabledFromDeviceConfig() {
final String value = DeviceConfig.getProperty(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_SERVICE_EXPLICITLY_ENABLED);
setDisabledByDeviceConfig(value);
@@ -327,13 +359,6 @@
}
}
- /**
- * Logs a request so it's dumped later...
- */
- void logRequestLocked(@NonNull String historyItem) {
- mRequestsHistory.log(historyItem);
- }
-
private ActivityManagerInternal getAmInternal() {
synchronized (mLock) {
if (mAm == null) {
@@ -527,9 +552,13 @@
synchronized (mLock) {
dumpLocked("", pw);
}
- if (showHistory) {
- pw.println(); pw.println("Requests history:"); pw.println();
+ pw.print("Requests history: ");
+ if (mRequestsHistory == null) {
+ pw.println("disabled by device config");
+ } else if (showHistory) {
+ pw.println();
mRequestsHistory.reverseDump(fd, pw, args);
+ pw.println();
}
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 7102b82..7150264 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -187,13 +187,15 @@
final ComponentName componentName = activityPresentationInfo.componentName;
final ComponentName serviceComponentName = getServiceComponentName();
final boolean enabled = isEnabledLocked();
- final String historyItem =
- "id=" + sessionId + " uid=" + uid
- + " a=" + ComponentName.flattenToShortString(componentName)
- + " t=" + taskId + " d=" + displayId
- + " s=" + ComponentName.flattenToShortString(serviceComponentName)
- + " u=" + mUserId + " f=" + flags + (enabled ? "" : " (disabled)");
- mMaster.logRequestLocked(historyItem);
+ if (mMaster.mRequestsHistory != null) {
+ final String historyItem =
+ "id=" + sessionId + " uid=" + uid
+ + " a=" + ComponentName.flattenToShortString(componentName)
+ + " t=" + taskId + " d=" + displayId
+ + " s=" + ComponentName.flattenToShortString(serviceComponentName)
+ + " u=" + mUserId + " f=" + flags + (enabled ? "" : " (disabled)");
+ mMaster.mRequestsHistory.log(historyItem);
+ }
if (!enabled) {
// TODO: it would be better to split in differet reasons, like
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
index 4ed5c3d..4094843 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
@@ -20,6 +20,7 @@
import android.os.IBinder;
import android.service.contentcapture.ContentCaptureService;
import android.service.contentcapture.SnapshotData;
+import android.util.LocalLog;
import android.util.Slog;
import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureSessionId;
@@ -86,7 +87,10 @@
*/
@GuardedBy("mLock")
public void sendActivitySnapshotLocked(@NonNull SnapshotData snapshotData) {
- mService.getMaster().logRequestLocked("snapshot: id=" + mId);
+ final LocalLog logHistory = mService.getMaster().mRequestsHistory;
+ if (logHistory != null) {
+ logHistory.log("snapshot: id=" + mId);
+ }
mRemoteService.onActivitySnapshotRequest(mId, snapshotData);
}
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index f293328..47c9b86 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -104,8 +104,7 @@
@Override
public void onSwitchUser(int userId) {
- cancelAndUnbindLocked(peekUserStateLocked(userId),
- AttentionService.ATTENTION_FAILURE_UNKNOWN);
+ cancelAndUnbindLocked(peekUserStateLocked(userId));
}
/** Resolves and sets up the attention service if it had not been done yet. */
@@ -152,7 +151,8 @@
}
synchronized (mLock) {
- unbindAfterTimeoutLocked();
+ final long now = SystemClock.uptimeMillis();
+ freeIfInactiveLocked();
final UserState userState = getOrCreateCurrentUserStateLocked();
// lazily start the service, which should be very lightweight to start
@@ -172,7 +172,7 @@
try {
// throttle frequent requests
final AttentionCheckCache attentionCheckCache = userState.mAttentionCheckCache;
- if (attentionCheckCache != null && SystemClock.uptimeMillis()
+ if (attentionCheckCache != null && now
< attentionCheckCache.mLastComputed + STALE_AFTER_MILLIS) {
callback.onSuccess(requestCode, attentionCheckCache.mResult,
attentionCheckCache.mTimestamp);
@@ -190,6 +190,7 @@
userState.mAttentionCheckCache = new AttentionCheckCache(
SystemClock.uptimeMillis(), result,
timestamp);
+ userState.mCurrentAttentionCheckIsFulfilled = true;
}
StatsLog.write(StatsLog.ATTENTION_MANAGER_SERVICE_RESULT_REPORTED,
result);
@@ -198,6 +199,7 @@
@Override
public void onFailure(int requestCode, int error) {
callback.onFailure(requestCode, error);
+ userState.mCurrentAttentionCheckIsFulfilled = true;
StatsLog.write(StatsLog.ATTENTION_MANAGER_SERVICE_RESULT_REPORTED,
error);
}
@@ -214,7 +216,10 @@
/** Cancels the specified attention check. */
public void cancelAttentionCheck(int requestCode) {
synchronized (mLock) {
- final UserState userState = getOrCreateCurrentUserStateLocked();
+ final UserState userState = peekCurrentUserStateLocked();
+ if (userState == null) {
+ return;
+ }
if (userState.mService == null) {
if (userState.mPendingAttentionCheck != null
&& userState.mPendingAttentionCheck.mRequestCode == requestCode) {
@@ -231,8 +236,12 @@
}
@GuardedBy("mLock")
- private void unbindAfterTimeoutLocked() {
- mAttentionHandler.sendEmptyMessageDelayed(AttentionHandler.CONNECTION_EXPIRED,
+ private void freeIfInactiveLocked() {
+ // If we are called here, it means someone used the API again - reset the timer then.
+ mAttentionHandler.removeMessages(AttentionHandler.CHECK_CONNECTION_EXPIRATION);
+
+ // Schedule resources cleanup if no one calls the API again.
+ mAttentionHandler.sendEmptyMessageDelayed(AttentionHandler.CHECK_CONNECTION_EXPIRATION,
CONNECTION_TTL_MILLIS);
}
@@ -259,12 +268,14 @@
}
@GuardedBy("mLock")
- UserState peekCurrentUserStateLocked() {
+ @Nullable
+ private UserState peekCurrentUserStateLocked() {
return peekUserStateLocked(ActivityManager.getCurrentUser());
}
@GuardedBy("mLock")
- UserState peekUserStateLocked(int userId) {
+ @Nullable
+ private UserState peekUserStateLocked(int userId) {
return mUserStates.get(userId);
}
@@ -401,6 +412,8 @@
@GuardedBy("mLock")
int mCurrentAttentionCheckRequestCode;
@GuardedBy("mLock")
+ boolean mCurrentAttentionCheckIsFulfilled;
+ @GuardedBy("mLock")
PendingAttentionCheck mPendingAttentionCheck;
@GuardedBy("mLock")
@@ -496,7 +509,7 @@
}
private class AttentionHandler extends Handler {
- private static final int CONNECTION_EXPIRED = 1;
+ private static final int CHECK_CONNECTION_EXPIRATION = 1;
private static final int ATTENTION_CHECK_TIMEOUT = 2;
AttentionHandler() {
@@ -506,19 +519,26 @@
public void handleMessage(Message msg) {
switch (msg.what) {
// Do not occupy resources when not in use - unbind proactively.
- case CONNECTION_EXPIRED: {
+ case CHECK_CONNECTION_EXPIRATION: {
for (int i = 0; i < mUserStates.size(); i++) {
- cancelAndUnbindLocked(mUserStates.valueAt(i),
- AttentionService.ATTENTION_FAILURE_UNKNOWN);
+ cancelAndUnbindLocked(mUserStates.valueAt(i));
}
-
}
break;
// Callee is no longer interested in the attention check result - cancel.
case ATTENTION_CHECK_TIMEOUT: {
- cancelAndUnbindLocked(peekCurrentUserStateLocked(),
- AttentionService.ATTENTION_FAILURE_TIMED_OUT);
+ synchronized (mLock) {
+ final UserState userState = peekCurrentUserStateLocked();
+ if (userState != null) {
+ // If not called back already.
+ if (!userState.mCurrentAttentionCheckIsFulfilled) {
+ cancel(userState,
+ AttentionService.ATTENTION_FAILURE_TIMED_OUT);
+ }
+
+ }
+ }
}
break;
@@ -528,25 +548,29 @@
}
}
- @GuardedBy("mLock")
- private void cancelAndUnbindLocked(UserState userState,
- @AttentionFailureCodes int failureCode) {
- synchronized (mLock) {
- if (userState != null && userState.mService != null) {
- try {
- userState.mService.cancelAttentionCheck(
- userState.mCurrentAttentionCheckRequestCode);
- } catch (RemoteException e) {
- Slog.e(LOG_TAG, "Unable to cancel attention check");
- }
-
- if (userState.mPendingAttentionCheck != null) {
- userState.mPendingAttentionCheck.cancel(failureCode);
- }
- mContext.unbindService(userState.mConnection);
- userState.mConnection.cleanupService();
- mUserStates.remove(userState.mUserId);
+ private void cancel(UserState userState, @AttentionFailureCodes int failureCode) {
+ if (userState != null && userState.mService != null) {
+ try {
+ userState.mService.cancelAttentionCheck(
+ userState.mCurrentAttentionCheckRequestCode);
+ } catch (RemoteException e) {
+ Slog.e(LOG_TAG, "Unable to cancel attention check");
}
+
+ if (userState.mPendingAttentionCheck != null) {
+ userState.mPendingAttentionCheck.cancel(failureCode);
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void cancelAndUnbindLocked(UserState userState) {
+ synchronized (mLock) {
+ cancel(userState, AttentionService.ATTENTION_FAILURE_UNKNOWN);
+
+ mContext.unbindService(userState.mConnection);
+ userState.mConnection.cleanupService();
+ mUserStates.remove(userState.mUserId);
}
}
@@ -558,8 +582,7 @@
@Override
public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
- cancelAndUnbindLocked(peekCurrentUserStateLocked(),
- AttentionService.ATTENTION_FAILURE_UNKNOWN);
+ cancelAndUnbindLocked(peekCurrentUserStateLocked());
}
}
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 1a62d4f..d902201 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -754,6 +754,7 @@
intentFilter.addAction(Intent.ACTION_USER_FOREGROUND);
intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+ intentFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
@@ -5183,6 +5184,20 @@
} else if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) ||
action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) {
handleAudioEffectBroadcast(context, intent);
+ } else if (action.equals(Intent.ACTION_PACKAGES_SUSPENDED)) {
+ final int[] suspendedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
+ final String[] suspendedPackages =
+ intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ if (suspendedPackages == null || suspendedUids == null
+ || suspendedPackages.length != suspendedUids.length) {
+ return;
+ }
+ for (int i = 0; i < suspendedUids.length; i++) {
+ if (!TextUtils.isEmpty(suspendedPackages[i])) {
+ mMediaFocusControl.noFocusForSuspendedApp(
+ suspendedPackages[i], suspendedUids[i]);
+ }
+ }
}
}
} // end class AudioServiceBroadcastReceiver
@@ -5347,6 +5362,11 @@
}
}
+ if (callingPackageName == null || clientId == null || aa == null) {
+ Log.e(TAG, "Invalid null parameter to request audio focus");
+ return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ }
+
return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
clientId, callingPackageName, flags, sdk,
forceFocusDuckingForAccessibility(aa, durationHint, Binder.getCallingUid()));
diff --git a/services/core/java/com/android/server/audio/FocusRequester.java b/services/core/java/com/android/server/audio/FocusRequester.java
index 99f0840..db55138 100644
--- a/services/core/java/com/android/server/audio/FocusRequester.java
+++ b/services/core/java/com/android/server/audio/FocusRequester.java
@@ -45,8 +45,8 @@
private AudioFocusDeathHandler mDeathHandler; // may be null
private IAudioFocusDispatcher mFocusDispatcher; // may be null
private final IBinder mSourceRef; // may be null
- private final String mClientId;
- private final String mPackageName;
+ private final @NonNull String mClientId;
+ private final @NonNull String mPackageName;
private final int mCallingUid;
private final MediaFocusControl mFocusController; // never null
private final int mSdkTarget;
@@ -72,7 +72,7 @@
/**
* the audio attributes associated with the focus request
*/
- private final AudioAttributes mAttributes;
+ private final @NonNull AudioAttributes mAttributes;
/**
* Class constructor
@@ -87,9 +87,10 @@
* @param uid
* @param ctlr cannot be null
*/
- FocusRequester(AudioAttributes aa, int focusRequest, int grantFlags,
- IAudioFocusDispatcher afl, IBinder source, String id, AudioFocusDeathHandler hdlr,
- String pn, int uid, @NonNull MediaFocusControl ctlr, int sdk) {
+ FocusRequester(@NonNull AudioAttributes aa, int focusRequest, int grantFlags,
+ IAudioFocusDispatcher afl, IBinder source, @NonNull String id,
+ AudioFocusDeathHandler hdlr, @NonNull String pn, int uid,
+ @NonNull MediaFocusControl ctlr, int sdk) {
mAttributes = aa;
mFocusDispatcher = afl;
mSourceRef = source;
@@ -124,11 +125,7 @@
}
boolean hasSameClient(String otherClient) {
- try {
- return mClientId.compareTo(otherClient) == 0;
- } catch (NullPointerException e) {
- return false;
- }
+ return mClientId.compareTo(otherClient) == 0;
}
boolean isLockedFocusOwner() {
@@ -143,12 +140,8 @@
return (mFocusDispatcher != null) && mFocusDispatcher.equals(fd);
}
- boolean hasSamePackage(String pack) {
- try {
- return mPackageName.compareTo(pack) == 0;
- } catch (NullPointerException e) {
- return false;
- }
+ boolean hasSamePackage(@NonNull String pack) {
+ return mPackageName.compareTo(pack) == 0;
}
boolean hasSameUid(int uid) {
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index d023bd7..b4bbbc7 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -24,7 +24,6 @@
import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.IAudioFocusDispatcher;
-import android.media.audiopolicy.AudioPolicy;
import android.media.audiopolicy.IAudioPolicyCallback;
import android.os.Binder;
import android.os.Build;
@@ -35,6 +34,7 @@
import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter;
+import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
@@ -44,7 +44,6 @@
import java.util.Map.Entry;
import java.util.Set;
import java.util.Stack;
-import java.text.DateFormat;
/**
* @hide
@@ -138,6 +137,30 @@
private static final AudioEventLogger mEventLogger = new AudioEventLogger(50,
"focus commands as seen by MediaFocusControl");
+ /*package*/ void noFocusForSuspendedApp(@NonNull String packageName, int uid) {
+ synchronized (mAudioFocusLock) {
+ final Iterator<FocusRequester> stackIterator = mFocusStack.iterator();
+ List<String> clientsToRemove = new ArrayList<>();
+ while (stackIterator.hasNext()) {
+ final FocusRequester focusOwner = stackIterator.next();
+ if (focusOwner.hasSameUid(uid) && focusOwner.hasSamePackage(packageName)) {
+ clientsToRemove.add(focusOwner.getClientId());
+ mEventLogger.log((new AudioEventLogger.StringEvent(
+ "focus owner:" + focusOwner.getClientId()
+ + " in uid:" + uid + " pack: " + packageName
+ + " getting AUDIOFOCUS_LOSS due to app suspension"))
+ .printLog(TAG));
+ // make the suspended app lose focus through its focus listener (if any)
+ focusOwner.dispatchFocusChange(AudioManager.AUDIOFOCUS_LOSS);
+ }
+ }
+ for (String clientToRemove : clientsToRemove) {
+ // update the stack but don't signal the change.
+ removeFocusStackEntry(clientToRemove, false, true);
+ }
+ }
+ }
+
/**
* Discard the current audio focus owner.
* Notify top of audio focus stack that it lost focus (regardless of possibility to reassign
@@ -688,9 +711,9 @@
}
/** @see AudioManager#requestAudioFocus(AudioManager.OnAudioFocusChangeListener, int, int, int) */
- protected int requestAudioFocus(AudioAttributes aa, int focusChangeHint, IBinder cb,
- IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
- int sdk, boolean forceDuck) {
+ protected int requestAudioFocus(@NonNull AudioAttributes aa, int focusChangeHint, IBinder cb,
+ IAudioFocusDispatcher fd, @NonNull String clientId, @NonNull String callingPackageName,
+ int flags, int sdk, boolean forceDuck) {
mEventLogger.log((new AudioEventLogger.StringEvent(
"requestAudioFocus() from uid/pid " + Binder.getCallingUid()
+ "/" + Binder.getCallingPid()
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index e479a15..d0c59c1 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -320,6 +320,11 @@
private final class PackageReceiver extends BroadcastReceiver {
@Override
public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
+ final String action = intent.getAction();
+ if (action == null) {
+ Slog.e(TAG, "Cannot handle package broadcast with null action");
+ return;
+ }
final Uri data = intent.getData();
if (data == null) {
Slog.e(TAG, "Cannot handle package broadcast with null data");
@@ -337,7 +342,7 @@
userIds = new int[] { UserHandle.getUserId(extraUid) };
}
- switch (intent.getAction()) {
+ switch (action) {
case ACTION_PACKAGE_ADDED:
if (replacing) {
onPackageUpgraded(packageName, userIds);
diff --git a/services/core/java/com/android/server/policy/DisplayFoldController.java b/services/core/java/com/android/server/policy/DisplayFoldController.java
index fdcafa7..0c6b773 100644
--- a/services/core/java/com/android/server/policy/DisplayFoldController.java
+++ b/services/core/java/com/android/server/policy/DisplayFoldController.java
@@ -42,10 +42,12 @@
private final WindowManagerInternal mWindowManagerInternal;
private final DisplayManagerInternal mDisplayManagerInternal;
private final int mDisplayId;
+ private final Handler mHandler;
/** The display area while device is folded. */
private final Rect mFoldedArea;
- private final Handler mHandler;
+ /** The display area to override the original folded area. */
+ private Rect mOverrideFoldedArea = new Rect();
private final DisplayInfo mNonOverrideDisplayInfo = new DisplayInfo();
private final RemoteCallbackList<IDisplayFoldListener> mListeners = new RemoteCallbackList<>();
@@ -70,14 +72,23 @@
return;
}
if (folded) {
- mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mNonOverrideDisplayInfo);
- final int dx = (mNonOverrideDisplayInfo.logicalWidth - mFoldedArea.width()) / 2
- - mFoldedArea.left;
- final int dy = (mNonOverrideDisplayInfo.logicalHeight - mFoldedArea.height()) / 2
- - mFoldedArea.top;
+ Rect foldedArea;
+ if (!mOverrideFoldedArea.isEmpty()) {
+ foldedArea = mOverrideFoldedArea;
+ } else if (!mFoldedArea.isEmpty()) {
+ foldedArea = mFoldedArea;
+ } else {
+ return;
+ }
- mWindowManagerInternal.setForcedDisplaySize(mDisplayId, mFoldedArea.width(),
- mFoldedArea.height());
+ mDisplayManagerInternal.getNonOverrideDisplayInfo(mDisplayId, mNonOverrideDisplayInfo);
+ final int dx = (mNonOverrideDisplayInfo.logicalWidth - foldedArea.width()) / 2
+ - foldedArea.left;
+ final int dy = (mNonOverrideDisplayInfo.logicalHeight - foldedArea.height()) / 2
+ - foldedArea.top;
+
+ mWindowManagerInternal.setForcedDisplaySize(mDisplayId,
+ foldedArea.width(), foldedArea.height());
mDisplayManagerInternal.setDisplayOffsets(mDisplayId, -dx, -dy);
} else {
mWindowManagerInternal.clearForcedDisplaySize(mDisplayId);
@@ -114,6 +125,18 @@
mListeners.unregister(listener);
}
+ void setOverrideFoldedArea(Rect area) {
+ mOverrideFoldedArea.set(area);
+ }
+
+ Rect getFoldedArea() {
+ if (!mOverrideFoldedArea.isEmpty()) {
+ return mOverrideFoldedArea;
+ } else {
+ return mFoldedArea;
+ }
+ }
+
/**
* Only used for the case that persist.debug.force_foldable is set.
* This is using proximity sensor to simulate the fold state switch.
@@ -125,7 +148,7 @@
return null;
}
- final DisplayFoldController result = create(displayId);
+ final DisplayFoldController result = create(context, displayId);
sensorManager.registerListener(new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
@@ -141,13 +164,17 @@
return result;
}
- static DisplayFoldController create(int displayId) {
+ static DisplayFoldController create(Context context, int displayId) {
final DisplayManagerInternal displayService =
LocalServices.getService(DisplayManagerInternal.class);
- final DisplayInfo displayInfo = new DisplayInfo();
- displayService.getNonOverrideDisplayInfo(displayId, displayInfo);
- final Rect foldedArea = new Rect(0, displayInfo.logicalHeight / 2,
- displayInfo.logicalWidth, displayInfo.logicalHeight);
+ final String configFoldedArea = context.getResources().getString(
+ com.android.internal.R.string.config_foldedArea);
+ final Rect foldedArea;
+ if (configFoldedArea == null || configFoldedArea.isEmpty()) {
+ foldedArea = new Rect();
+ } else {
+ foldedArea = Rect.unflattenFromString(configFoldedArea);
+ }
return new DisplayFoldController(LocalServices.getService(WindowManagerInternal.class),
displayService, displayId, foldedArea, DisplayThread.getHandler());
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 2e3e3e4..c87a81d 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -125,6 +125,7 @@
import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.graphics.PixelFormat;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.hardware.display.DisplayManager;
import android.hardware.hdmi.HdmiAudioSystemClient;
@@ -1858,7 +1859,7 @@
readConfigurationDependentBehaviors();
if (mLidControlsDisplayFold) {
- mDisplayFoldController = DisplayFoldController.create(DEFAULT_DISPLAY);
+ mDisplayFoldController = DisplayFoldController.create(context, DEFAULT_DISPLAY);
} else if (SystemProperties.getBoolean("persist.debug.force_foldable", false)) {
mDisplayFoldController = DisplayFoldController.createWithProxSensor(context,
DEFAULT_DISPLAY);
@@ -3221,6 +3222,21 @@
}
@Override
+ public void setOverrideFoldedArea(Rect area) {
+ if (mDisplayFoldController != null) {
+ mDisplayFoldController.setOverrideFoldedArea(area);
+ }
+ }
+
+ @Override
+ public Rect getFoldedArea() {
+ if (mDisplayFoldController != null) {
+ return mDisplayFoldController.getFoldedArea();
+ }
+ return new Rect();
+ }
+
+ @Override
public void registerShortcutKey(long shortcutCode, IShortcutService shortcutService)
throws RemoteException {
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 870d61b..d7e4b6c 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -64,6 +64,7 @@
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.content.Context;
@@ -1470,6 +1471,20 @@
default void unregisterDisplayFoldListener(IDisplayFoldListener listener) {}
/**
+ * Overrides the folded area.
+ *
+ * @param area the overriding folded area or an empty {@code Rect} to clear the override.
+ */
+ default void setOverrideFoldedArea(@NonNull Rect area) {}
+
+ /**
+ * Get the display folded area.
+ */
+ default @NonNull Rect getFoldedArea() {
+ return new Rect();
+ }
+
+ /**
* Updates the flag about whether AOD is showing.
*
* @return whether the value was changed.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 899bf7c..7beee0e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -22,6 +22,7 @@
import static android.Manifest.permission.READ_FRAME_BUFFER;
import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
import static android.Manifest.permission.RESTRICTED_VR_ACCESS;
+import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
@@ -3759,6 +3760,41 @@
mPolicy.unregisterDisplayFoldListener(listener);
}
+ /**
+ * Overrides the folded area.
+ *
+ * @param area the overriding folded area or an empty {@code Rect} to clear the override.
+ */
+ void setOverrideFoldedArea(@NonNull Rect area) {
+ if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
+ }
+
+ long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ mPolicy.setOverrideFoldedArea(area);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ /**
+ * Get the display folded area.
+ */
+ @NonNull Rect getFoldedArea() {
+ long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ return mPolicy.getFoldedArea();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
@Override
public int getPreferredOptionsPanelGravity(int displayId) {
synchronized (mGlobalLock) {
@@ -4826,11 +4862,9 @@
@Override
public void setForcedDisplaySize(int displayId, int width, int height) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold permission " +
- android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
}
final long ident = Binder.clearCallingIdentity();
@@ -4848,11 +4882,9 @@
@Override
public void setForcedDisplayScalingMode(int displayId, int mode) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold permission " +
- android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
}
final long ident = Binder.clearCallingIdentity();
@@ -4917,11 +4949,9 @@
@Override
public void clearForcedDisplaySize(int displayId) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold permission " +
- android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
}
final long ident = Binder.clearCallingIdentity();
@@ -4962,11 +4992,9 @@
@Override
public void setForcedDisplayDensityForUser(int displayId, int density, int userId) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold permission " +
- android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
}
final int targetUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
@@ -4987,11 +5015,9 @@
@Override
public void clearForcedDisplayDensityForUser(int displayId, int userId) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold permission " +
- android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
}
final int callingUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
@@ -5056,11 +5082,9 @@
@Override
public void setOverscan(int displayId, int left, int top, int right, int bottom) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
- PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Must hold permission " +
- android.Manifest.permission.WRITE_SECURE_SETTINGS);
+ if (mContext.checkCallingOrSelfPermission(WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Must hold permission " + WRITE_SECURE_SETTINGS);
}
final long ident = Binder.clearCallingIdentity();
try {
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index 83e3c71..d13ee45 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -62,6 +62,8 @@
return runDisplaySize(pw);
case "density":
return runDisplayDensity(pw);
+ case "folded-area":
+ return runDisplayFoldedArea(pw);
case "overscan":
return runDisplayOverscan(pw);
case "scaling":
@@ -207,6 +209,40 @@
return 0;
}
+ private void printFoldedArea(PrintWriter pw) {
+ final Rect foldedArea = mInternal.getFoldedArea();
+ if (foldedArea.isEmpty()) {
+ pw.println("Folded area: none");
+ } else {
+ pw.println("Folded area: " + foldedArea.left + "," + foldedArea.top + ","
+ + foldedArea.right + "," + foldedArea.bottom);
+ }
+ }
+
+ private int runDisplayFoldedArea(PrintWriter pw) {
+ final String areaStr = getNextArg();
+ final Rect rect = new Rect();
+ if (areaStr == null) {
+ printFoldedArea(pw);
+ return 0;
+ } else if ("reset".equals(areaStr)) {
+ rect.setEmpty();
+ } else {
+ final Pattern flattenedPattern = Pattern.compile(
+ "(-?\\d+),(-?\\d+),(-?\\d+),(-?\\d+)");
+ final Matcher matcher = flattenedPattern.matcher(areaStr);
+ if (!matcher.matches()) {
+ getErrPrintWriter().println("Error: area should be LEFT,TOP,RIGHT,BOTTOM");
+ return -1;
+ }
+ rect.set(Integer.parseInt(matcher.group(1)), Integer.parseInt(matcher.group(2)),
+ Integer.parseInt(matcher.group(3)), Integer.parseInt(matcher.group(4)));
+ }
+
+ mInternal.setOverrideFoldedArea(rect);
+ return 0;
+ }
+
private int runDisplayOverscan(PrintWriter pw) throws RemoteException {
String overscanStr = getNextArgRequired();
Rect rect = new Rect();
@@ -335,6 +371,8 @@
pw.println(" width and height in pixels unless suffixed with 'dp'.");
pw.println(" density [reset|DENSITY] [-d DISPLAY_ID]");
pw.println(" Return or override display density.");
+ pw.println(" folded-area [reset|LEFT,TOP,RIGHT,BOTTOM]");
+ pw.println(" Return or override folded area.");
pw.println(" overscan [reset|LEFT,TOP,RIGHT,BOTTOM] [-d DISPLAY ID]");
pw.println(" Set overscan area for display.");
pw.println(" scaling [off|auto] [-d DISPLAY_ID]");
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 9946cc3..8ad4d76 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -3,6 +3,7 @@
srcs: ["java/**/*.java"],
static_libs: [
"netd_aidl_interface-java",
+ "networkstack-aidl-interfaces-java",
]
}
diff --git a/core/java/android/net/dhcp/DhcpServerCallbacks.java b/services/net/java/android/net/dhcp/DhcpServerCallbacks.java
similarity index 100%
rename from core/java/android/net/dhcp/DhcpServerCallbacks.java
rename to services/net/java/android/net/dhcp/DhcpServerCallbacks.java
diff --git a/core/java/android/net/ip/IpClientCallbacks.java b/services/net/java/android/net/ip/IpClientCallbacks.java
similarity index 100%
rename from core/java/android/net/ip/IpClientCallbacks.java
rename to services/net/java/android/net/ip/IpClientCallbacks.java
diff --git a/services/usage/java/com/android/server/usage/IntervalStats.java b/services/usage/java/com/android/server/usage/IntervalStats.java
index f1ddfe4..8feed7f 100644
--- a/services/usage/java/com/android/server/usage/IntervalStats.java
+++ b/services/usage/java/com/android/server/usage/IntervalStats.java
@@ -15,7 +15,6 @@
*/
package com.android.server.usage;
-import static android.app.usage.UsageEvents.Event.ACTIVITY_DESTROYED;
import static android.app.usage.UsageEvents.Event.ACTIVITY_PAUSED;
import static android.app.usage.UsageEvents.Event.ACTIVITY_RESUMED;
import static android.app.usage.UsageEvents.Event.ACTIVITY_STOPPED;
@@ -302,27 +301,6 @@
UsageStats usageStats = packageStats.valueAt(i);
usageStats.update(null, timeStamp, eventType, instanceId);
}
- } else if (eventType == ACTIVITY_DESTROYED) {
- UsageStats usageStats = packageStats.get(packageName);
- if (usageStats != null) {
- // If previous event is not ACTIVITY_STOPPED, convert ACTIVITY_DESTROYED
- // to ACTIVITY_STOPPED and add to event list.
- // Otherwise do not add anything to event list. (Because we want to save space
- // and we do not want a ACTIVITY_STOPPED followed by
- // ACTIVITY_DESTROYED in event list).
- final int index = usageStats.mActivities.indexOfKey(instanceId);
- if (index >= 0) {
- final int type = usageStats.mActivities.valueAt(index);
- if (type != ACTIVITY_STOPPED) {
- Event event = new Event(ACTIVITY_STOPPED, timeStamp);
- event.mPackage = packageName;
- event.mClass = className;
- event.mInstanceId = instanceId;
- addEvent(event);
- }
- }
- usageStats.update(className, timeStamp, ACTIVITY_DESTROYED, instanceId);
- }
} else {
UsageStats usageStats = getOrCreateUsageStats(packageName);
usageStats.update(className, timeStamp, eventType, instanceId);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index af5278f..ebb0210 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -145,8 +145,16 @@
AppTimeLimitController mAppTimeLimit;
final SparseArray<ArraySet<String>> mUsageReporters = new SparseArray();
- final SparseArray<String> mVisibleActivities = new SparseArray();
+ final SparseArray<ActivityData> mVisibleActivities = new SparseArray();
+ private static class ActivityData {
+ private final String mTaskRootPackage;
+ private final String mTaskRootClass;
+ private ActivityData(String taskRootPackage, String taskRootClass) {
+ mTaskRootPackage = taskRootPackage;
+ mTaskRootClass = taskRootClass;
+ }
+ }
private UsageStatsManagerInternal.AppIdleStateChangeListener mStandbyChangeListener =
new UsageStatsManagerInternal.AppIdleStateChangeListener() {
@@ -464,47 +472,57 @@
final long elapsedRealtime = SystemClock.elapsedRealtime();
convertToSystemTimeLocked(event);
- if (event.getPackageName() != null
- && mPackageManagerInternal.isPackageEphemeral(userId, event.getPackageName())) {
+ if (event.mPackage != null
+ && mPackageManagerInternal.isPackageEphemeral(userId, event.mPackage)) {
event.mFlags |= Event.FLAG_IS_PACKAGE_INSTANT_APP;
}
- final UserUsageStatsService service =
- getUserDataAndInitializeIfNeededLocked(userId, timeNow);
- service.reportEvent(event);
-
- mAppStandby.reportEvent(event, elapsedRealtime, userId);
-
- String packageName;
-
- switch(mUsageSource) {
- case USAGE_SOURCE_CURRENT_ACTIVITY:
- packageName = event.getPackageName();
- break;
- case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
- default:
- packageName = event.getTaskRootPackageName();
- if (packageName == null) {
- packageName = event.getPackageName();
- }
- break;
- }
-
switch (event.mEventType) {
case Event.ACTIVITY_RESUMED:
- synchronized (mVisibleActivities) {
- // check if this activity has already been resumed
- if (mVisibleActivities.get(event.mInstanceId) != null) break;
- mVisibleActivities.put(event.mInstanceId, event.getClassName());
- try {
- mAppTimeLimit.noteUsageStart(packageName, userId);
- } catch (IllegalArgumentException iae) {
- Slog.e(TAG, "Failed to note usage start", iae);
+ // check if this activity has already been resumed
+ if (mVisibleActivities.get(event.mInstanceId) != null) break;
+ mVisibleActivities.put(event.mInstanceId,
+ new ActivityData(event.mTaskRootPackage, event.mTaskRootClass));
+ try {
+ switch(mUsageSource) {
+ case USAGE_SOURCE_CURRENT_ACTIVITY:
+ mAppTimeLimit.noteUsageStart(event.mPackage, userId);
+ break;
+ case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
+ default:
+ mAppTimeLimit.noteUsageStart(event.mTaskRootPackage, userId);
+ break;
+ }
+ } catch (IllegalArgumentException iae) {
+ Slog.e(TAG, "Failed to note usage start", iae);
+ }
+ break;
+ case Event.ACTIVITY_PAUSED:
+ if (event.mTaskRootPackage == null) {
+ // Task Root info is missing. Repair the event based on previous data
+ final ActivityData prevData = mVisibleActivities.get(event.mInstanceId);
+ if (prevData == null) {
+ Slog.w(TAG, "Unexpected activity event reported! (" + event.mPackage
+ + "/" + event.mClass + " event : " + event.mEventType
+ + " instanceId : " + event.mInstanceId + ")");
+ } else {
+ event.mTaskRootPackage = prevData.mTaskRootPackage;
+ event.mTaskRootClass = prevData.mTaskRootClass;
}
}
break;
- case Event.ACTIVITY_STOPPED:
case Event.ACTIVITY_DESTROYED:
+ // Treat activity destroys like activity stops.
+ event.mEventType = Event.ACTIVITY_STOPPED;
+ // Fallthrough
+ case Event.ACTIVITY_STOPPED:
+ final ActivityData prevData =
+ mVisibleActivities.removeReturnOld(event.mInstanceId);
+ if (prevData == null) {
+ // The activity stop was already handled.
+ return;
+ }
+
ArraySet<String> tokens;
synchronized (mUsageReporters) {
tokens = mUsageReporters.removeReturnOld(event.mInstanceId);
@@ -517,7 +535,7 @@
final String token = tokens.valueAt(i);
try {
mAppTimeLimit.noteUsageStop(
- buildFullToken(event.getPackageName(), token), userId);
+ buildFullToken(event.mPackage, token), userId);
} catch (IllegalArgumentException iae) {
Slog.w(TAG, "Failed to stop usage for during reporter death: "
+ iae);
@@ -525,18 +543,32 @@
}
}
}
-
- synchronized (mVisibleActivities) {
- if (mVisibleActivities.removeReturnOld(event.mInstanceId) != null) {
- try {
- mAppTimeLimit.noteUsageStop(packageName, userId);
- } catch (IllegalArgumentException iae) {
- Slog.w(TAG, "Failed to note usage stop", iae);
- }
+ if (event.mTaskRootPackage == null) {
+ // Task Root info is missing. Repair the event based on previous data
+ event.mTaskRootPackage = prevData.mTaskRootPackage;
+ event.mTaskRootClass = prevData.mTaskRootClass;
+ }
+ try {
+ switch(mUsageSource) {
+ case USAGE_SOURCE_CURRENT_ACTIVITY:
+ mAppTimeLimit.noteUsageStop(event.mPackage, userId);
+ break;
+ case USAGE_SOURCE_TASK_ROOT_ACTIVITY:
+ default:
+ mAppTimeLimit.noteUsageStop(event.mTaskRootPackage, userId);
+ break;
}
+ } catch (IllegalArgumentException iae) {
+ Slog.w(TAG, "Failed to note usage stop", iae);
}
break;
}
+
+ final UserUsageStatsService service =
+ getUserDataAndInitializeIfNeededLocked(userId, timeNow);
+ service.reportEvent(event);
+
+ mAppStandby.reportEvent(event, elapsedRealtime, userId);
}
}
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index 5f664f5..9832485 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -435,7 +435,7 @@
const size_t NS = pool->size();
for (size_t s=0; s<NS; s++) {
String8 str = pool->string8ObjectAt(s);
- printer->Print(StringPrintf("String #%zd: %s\n", s, str.string()));
+ printer->Print(StringPrintf("String #%zd : %s\n", s, str.string()));
}
}
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index ab4805f..0032960 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -727,7 +727,7 @@
// This must be a FileReference.
std::unique_ptr<FileReference> file_ref =
util::make_unique<FileReference>(dst_pool->MakeRef(
- str, StringPool::Context(StringPool::Context::kHighPriority, config), data));
+ str, StringPool::Context(StringPool::Context::kHighPriority, config)));
if (type == ResourceType::kRaw) {
file_ref->type = ResourceFile::Type::kUnknown;
} else if (util::EndsWith(*file_ref->path, ".xml")) {
@@ -739,7 +739,7 @@
}
// There are no styles associated with this string, so treat it as a simple string.
- return util::make_unique<String>(dst_pool->MakeRef(str, StringPool::Context(config), data));
+ return util::make_unique<String>(dst_pool->MakeRef(str, StringPool::Context(config)));
}
} break;
diff --git a/tools/aapt2/StringPool.cpp b/tools/aapt2/StringPool.cpp
index a8c2666..8eabd32 100644
--- a/tools/aapt2/StringPool.cpp
+++ b/tools/aapt2/StringPool.cpp
@@ -165,13 +165,12 @@
return MakeRefImpl(str, Context{}, true);
}
-StringPool::Ref StringPool::MakeRef(const StringPiece& str, const Context& context,
- Maybe<size_t> index) {
- return MakeRefImpl(str, context, true, index);
+StringPool::Ref StringPool::MakeRef(const StringPiece& str, const Context& context) {
+ return MakeRefImpl(str, context, true);
}
StringPool::Ref StringPool::MakeRefImpl(const StringPiece& str, const Context& context,
- bool unique, Maybe<size_t> index) {
+ bool unique) {
if (unique) {
auto range = indexed_strings_.equal_range(str);
for (auto iter = range.first; iter != range.second; ++iter) {
@@ -181,26 +180,15 @@
}
}
- const size_t size = strings_.size();
- // Insert the string at the end of the string vector if no index is specified
- const size_t insertion_index = index ? index.value() : size;
-
std::unique_ptr<Entry> entry(new Entry());
entry->value = str.to_string();
entry->context = context;
- entry->index_ = insertion_index;
+ entry->index_ = strings_.size();
entry->ref_ = 0;
entry->pool_ = this;
Entry* borrow = entry.get();
- if (insertion_index == size) {
- strings_.emplace_back(std::move(entry));
- } else {
- // Allocate enough space for the string at the index
- strings_.resize(std::max(insertion_index + 1, size));
- strings_[insertion_index] = std::move(entry);
- }
-
+ strings_.emplace_back(std::move(entry));
indexed_strings_.insert(std::make_pair(StringPiece(borrow->value), borrow));
return Ref(borrow);
}
diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h
index 115d5d3..1006ca9 100644
--- a/tools/aapt2/StringPool.h
+++ b/tools/aapt2/StringPool.h
@@ -166,8 +166,7 @@
// Adds a string to the pool, unless it already exists, with a context object that can be used
// when sorting the string pool. Returns a reference to the string in the pool.
- Ref MakeRef(const android::StringPiece& str, const Context& context,
- Maybe<size_t> index = {});
+ Ref MakeRef(const android::StringPiece& str, const Context& context);
// Adds a string from another string pool. Returns a reference to the string in the string pool.
Ref MakeRef(const Ref& ref);
@@ -211,8 +210,7 @@
static bool Flatten(BigBuffer* out, const StringPool& pool, bool utf8, IDiagnostics* diag);
- Ref MakeRefImpl(const android::StringPiece& str, const Context& context, bool unique,
- Maybe<size_t> index = {});
+ Ref MakeRefImpl(const android::StringPiece& str, const Context& context, bool unique);
void ReAssignIndices();
std::vector<std::unique_ptr<Entry>> strings_;
diff --git a/tools/aapt2/StringPool_test.cpp b/tools/aapt2/StringPool_test.cpp
index 648be7d..9a7238b 100644
--- a/tools/aapt2/StringPool_test.cpp
+++ b/tools/aapt2/StringPool_test.cpp
@@ -84,24 +84,6 @@
EXPECT_THAT(ref_c.index(), Eq(2u));
}
-TEST(StringPoolTest, AssignStringIndex) {
- StringPool pool;
-
- StringPool::Ref ref_a = pool.MakeRef("0", StringPool::Context{}, 0u);
- StringPool::Ref ref_b = pool.MakeRef("1", StringPool::Context{}, 1u);
- StringPool::Ref ref_c = pool.MakeRef("5", StringPool::Context{}, 5u);
- StringPool::Ref ref_d = pool.MakeRef("2", StringPool::Context{}, 2u);
- StringPool::Ref ref_e = pool.MakeRef("4", StringPool::Context{}, 4u);
- StringPool::Ref ref_f = pool.MakeRef("3", StringPool::Context{}, 3u);
-
- EXPECT_THAT(ref_a.index(), Eq(0u));
- EXPECT_THAT(ref_b.index(), Eq(1u));
- EXPECT_THAT(ref_d.index(), Eq(2u));
- EXPECT_THAT(ref_f.index(), Eq(3u));
- EXPECT_THAT(ref_e.index(), Eq(4u));
- EXPECT_THAT(ref_c.index(), Eq(5u));
-}
-
TEST(StringPoolTest, PruneStringsWithNoReferences) {
StringPool pool;
diff --git a/tools/aapt2/cmd/Convert.cpp b/tools/aapt2/cmd/Convert.cpp
index 7a74ba9..0cf86cc 100644
--- a/tools/aapt2/cmd/Convert.cpp
+++ b/tools/aapt2/cmd/Convert.cpp
@@ -43,7 +43,8 @@
class IApkSerializer {
public:
- IApkSerializer(IAaptContext* context, const Source& source) : context_(context), source_(source) {}
+ IApkSerializer(IAaptContext* context, const Source& source) : context_(context),
+ source_(source) {}
virtual bool SerializeXml(const xml::XmlResource* xml, const std::string& path, bool utf16,
IArchiveWriter* writer, uint32_t compression_flags) = 0;
@@ -167,7 +168,7 @@
std::unique_ptr<io::IData> data = file->file->OpenAsData();
if (!data) {
context_->GetDiagnostics()->Error(DiagMessage(source_)
- << "failed to open file " << *file->path);
+ << "failed to open file " << *file->path);
return false;
}
@@ -175,7 +176,7 @@
std::unique_ptr<xml::XmlResource> xml = xml::Inflate(data->data(), data->size(), &error);
if (xml == nullptr) {
context_->GetDiagnostics()->Error(DiagMessage(source_) << "failed to parse binary XML: "
- << error);
+ << error);
return false;
}
@@ -256,9 +257,6 @@
int Convert(IAaptContext* context, LoadedApk* apk, IArchiveWriter* output_writer,
ApkFormat output_format, TableFlattenerOptions table_flattener_options,
XmlFlattenerOptions xml_flattener_options) {
- // Do not change the ordering of strings in the values string pool
- table_flattener_options.sort_stringpool_entries = false;
-
unique_ptr<IApkSerializer> serializer;
if (output_format == ApkFormat::kBinary) {
serializer.reset(new BinaryApkSerializer(context, apk->GetSource(), table_flattener_options,
@@ -274,7 +272,7 @@
io::IFile* manifest = apk->GetFileCollection()->FindFile(kAndroidManifestPath);
if (!serializer->SerializeXml(apk->GetManifest(), kAndroidManifestPath, true /*utf16*/,
output_writer, (manifest != nullptr && manifest->WasCompressed())
- ? ArchiveEntry::kCompress : 0u)) {
+ ? ArchiveEntry::kCompress : 0u)) {
context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
<< "failed to serialize AndroidManifest.xml");
return 1;
@@ -303,8 +301,7 @@
if (files_written.insert(*file->path).second) {
if (!serializer->SerializeFile(file, output_writer)) {
context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
- << "failed to serialize file "
- << *file->path);
+ << "failed to serialize file " << *file->path);
return 1;
}
}
@@ -338,7 +335,7 @@
if (!io::CopyFileToArchivePreserveCompression(context, file, path, output_writer)) {
context->GetDiagnostics()->Error(DiagMessage(apk->GetSource())
- << "failed to copy file " << path);
+ << "failed to copy file " << path);
return 1;
}
}
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 8463046..4961aa5 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -400,7 +400,8 @@
static bool IsVectorElement(const std::string& name) {
return name == "vector" || name == "animated-vector" || name == "pathInterpolator" ||
- name == "objectAnimator" || name == "gradient" || name == "animated-selector";
+ name == "objectAnimator" || name == "gradient" || name == "animated-selector" ||
+ name == "set";
}
template <typename T>
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index 5d7e291..d677317 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -710,17 +710,15 @@
} // namespace
bool TableFlattener::Consume(IAaptContext* context, ResourceTable* table) {
- if (options_.sort_stringpool_entries) {
- // We must do this before writing the resources, since the string pool IDs may change.
- table->string_pool.Prune();
- table->string_pool.Sort([](const StringPool::Context &a, const StringPool::Context &b) -> int {
- int diff = util::compare(a.priority, b.priority);
- if (diff == 0) {
- diff = a.config.compare(b.config);
- }
- return diff;
- });
- }
+ // We must do this before writing the resources, since the string pool IDs may change.
+ table->string_pool.Prune();
+ table->string_pool.Sort([](const StringPool::Context& a, const StringPool::Context& b) -> int {
+ int diff = util::compare(a.priority, b.priority);
+ if (diff == 0) {
+ diff = a.config.compare(b.config);
+ }
+ return diff;
+ });
// Write the ResTable header.
ChunkWriter table_writer(buffer_);
diff --git a/tools/aapt2/format/binary/TableFlattener.h b/tools/aapt2/format/binary/TableFlattener.h
index 71330e3..73c1729 100644
--- a/tools/aapt2/format/binary/TableFlattener.h
+++ b/tools/aapt2/format/binary/TableFlattener.h
@@ -44,9 +44,6 @@
// Set of whitelisted resource names to avoid altering in key stringpool
std::set<std::string> whitelisted_resources;
- // When true, sort the entries in the values string pool by priority and configuration.
- bool sort_stringpool_entries = true;
-
// Map from original resource paths to shortened resource paths.
std::map<std::string, std::string> shortened_path_map;
};