Merge "Add CDM system api to check for association presence"
diff --git a/Android.bp b/Android.bp
index b26b373..d04eb17 100644
--- a/Android.bp
+++ b/Android.bp
@@ -34,6 +34,27 @@
path: "core/java",
}
+// These are subset of framework-core-sources that are needed by the
+// android.test.mock library. Ideally, the library should use public APIs only,
+// but unfortunately its API signature has some references to these private APIs.
+filegroup {
+ name: "framework-core-sources-for-test-mock",
+ srcs: [
+ "core/java/android/app/IApplicationThread.aidl",
+ "core/java/android/app/IServiceConnection.aidl",
+ "core/java/android/content/IContentProvider.java",
+ "core/java/android/content/pm/IPackageDataObserver.aidl",
+ "core/java/android/content/pm/InstantAppInfo.java",
+ "core/java/android/content/pm/KeySet.java",
+ "core/java/android/content/pm/PackageManager.java",
+ "core/java/android/content/pm/VerifierDeviceIdentity.java",
+ "core/java/android/content/res/Resources.java",
+ "core/java/android/os/storage/VolumeInfo.java",
+ "core/java/android/view/DisplayAdjustments.java",
+ ],
+ path: "core/java",
+}
+
filegroup {
name: "framework-drm-sources",
srcs: [
@@ -307,6 +328,7 @@
"android.hardware.thermal-V1.1-java",
"android.hardware.thermal-V2.0-java",
"android.hardware.tv.input-V1.0-java-constants",
+ "android.hardware.tv.tuner-V1.0-java-constants",
"android.hardware.usb-V1.0-java-constants",
"android.hardware.usb-V1.1-java-constants",
"android.hardware.usb-V1.2-java-constants",
@@ -935,10 +957,12 @@
]
metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
+ "--ignore-classes-on-classpath " +
"--hide-package com.android.okhttp " +
"--hide-package com.android.org.conscrypt --hide-package com.android.server " +
"--error UnhiddenSystemApi " +
"--hide RequiresPermission " +
+ "--hide CallbackInterface " +
"--hide MissingPermission --hide BroadcastBehavior " +
"--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
"--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
@@ -1422,8 +1446,6 @@
name: "hiddenapi-mappings",
defaults: ["metalava-api-stubs-default"],
srcs: [
- ":non_openjdk_java_files",
- ":openjdk_java_files",
":opt-telephony-common-srcs",
],
@@ -1439,29 +1461,6 @@
" --show-annotation android.annotation.TestApi ",
}
-filegroup {
- name: "apache-http-stubs-sources",
- srcs: [
- "core/java/org/apache/http/conn/ConnectTimeoutException.java",
- "core/java/org/apache/http/conn/scheme/HostNameResolver.java",
- "core/java/org/apache/http/conn/scheme/LayeredSocketFactory.java",
- "core/java/org/apache/http/conn/scheme/SocketFactory.java",
- "core/java/org/apache/http/conn/ssl/AbstractVerifier.java",
- "core/java/org/apache/http/conn/ssl/AllowAllHostnameVerifier.java",
- "core/java/org/apache/http/conn/ssl/AndroidDistinguishedNameParser.java",
- "core/java/org/apache/http/conn/ssl/BrowserCompatHostnameVerifier.java",
- "core/java/org/apache/http/conn/ssl/SSLSocketFactory.java",
- "core/java/org/apache/http/conn/ssl/StrictHostnameVerifier.java",
- "core/java/org/apache/http/conn/ssl/X509HostnameVerifier.java",
- "core/java/org/apache/http/params/CoreConnectionPNames.java",
- "core/java/org/apache/http/params/HttpConnectionParams.java",
- "core/java/org/apache/http/params/HttpParams.java",
- "core/java/android/net/http/SslCertificate.java",
- "core/java/android/net/http/SslError.java",
- "core/java/com/android/internal/util/HexDump.java",
- ],
-}
-
droidstubs {
name: "api-stubs-docs",
defaults: ["metalava-api-stubs-default"],
@@ -1537,6 +1536,10 @@
api_file: "api/test-current.txt",
removed_api_file: "api/test-removed.txt",
},
+ api_lint: {
+ enabled: true,
+ baseline_file: "api/test-lint-baseline.txt",
+ },
},
}
@@ -1596,13 +1599,16 @@
"core/java/android/util/Slog.java",
"core/java/android/util/TimeUtils.java",
"core/java/com/android/internal/os/SomeArgs.java",
+ "core/java/com/android/internal/util/ArrayUtils.java",
+ "core/java/com/android/internal/util/DumpUtils.java",
+ "core/java/com/android/internal/util/FastXmlSerializer.java",
+ "core/java/com/android/internal/util/HexDump.java",
+ "core/java/com/android/internal/util/IndentingPrintWriter.java",
"core/java/com/android/internal/util/Preconditions.java",
"core/java/com/android/internal/util/State.java",
"core/java/com/android/internal/util/StateMachine.java",
+ "core/java/com/android/internal/util/UserIcons.java",
"core/java/com/android/internal/util/XmlUtils.java",
- "core/java/com/android/internal/util/HexDump.java",
- "core/java/com/android/internal/util/IndentingPrintWriter.java",
- "core/java/com/android/internal/util/DumpUtils.java"
],
}
@@ -1621,7 +1627,6 @@
filegroup {
name: "framework-ims-common-shared-srcs",
srcs: [
- "core/java/android/os/AsyncResult.java",
"core/java/android/os/RegistrantList.java",
"core/java/android/os/Registrant.java",
"core/java/com/android/internal/os/SomeArgs.java",
@@ -1633,6 +1638,7 @@
name: "framework-wifistack-shared-srcs",
srcs: [
":framework-annotations",
+ "core/java/android/os/HandlerExecutor.java",
"core/java/android/util/KeyValueListParser.java",
"core/java/android/util/LocalLog.java",
"core/java/android/util/Rational.java",
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index e731138..6831117 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -1,8 +1,6 @@
[Hook Scripts]
checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT}
-api_lint_hook = ${REPO_ROOT}/frameworks/base/tools/apilint/apilint_sha.sh ${PREUPLOAD_COMMIT}
-
strings_lint_hook = ${REPO_ROOT}/frameworks/base/tools/stringslint/stringslint_sha.sh ${PREUPLOAD_COMMIT}
hidden_api_txt_checksorted_hook = ${REPO_ROOT}/frameworks/base/tools/hiddenapi/checksorted_sha.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
diff --git a/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java b/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java
index 5b14056..c264531 100644
--- a/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java
+++ b/apex/jobscheduler/framework/java/android/app/DeviceIdleFrameworkInitializer.java
@@ -19,36 +19,17 @@
import android.content.Context;
import android.os.DeviceIdleManager;
import android.os.IDeviceIdleController;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.ServiceManager;
/**
- * This class needs to be pre-loaded by zygote. This is where the device idle manager wrapper
- * is registered.
- *
* @hide
*/
public class DeviceIdleFrameworkInitializer {
private static IDeviceIdleController sIDeviceIdleController;
- static {
+ public static void initialize() {
SystemServiceRegistry.registerCachedService(
Context.DEVICE_IDLE_CONTROLLER, DeviceIdleManager.class,
(context, b) -> new DeviceIdleManager(
context, IDeviceIdleController.Stub.asInterface(b)));
- PowerManager.setIsIgnoringBatteryOptimizationsCallback((packageName) -> {
- // No need for synchronization on sIDeviceIdleController; worst case
- // we just initialize it twice.
- if (sIDeviceIdleController == null) {
- sIDeviceIdleController = IDeviceIdleController.Stub.asInterface(
- ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
- }
- try {
- return sIDeviceIdleController.isPowerSaveWhitelistApp(packageName);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- });
}
}
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
index 150cdbc..42cf17b 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
@@ -68,7 +68,11 @@
REASON_DEVICE_THERMAL,
};
- /** @hide */
+ /**
+ * @hide
+ * @deprecated use {@link #getReasonCodeDescription(int)}
+ */
+ @Deprecated
public static String getReasonName(int reason) {
switch (reason) {
case REASON_CANCELED: return "canceled";
@@ -81,6 +85,20 @@
}
}
+ /** @hide */
+ // @SystemApi TODO make it a system api for mainline
+ @NonNull
+ public static int[] getJobStopReasonCodes() {
+ return JOB_STOP_REASON_CODES;
+ }
+
+ /** @hide */
+ // @SystemApi TODO make it a system api for mainline
+ @NonNull
+ public static String getReasonCodeDescription(int reasonCode) {
+ return getReasonName(reasonCode);
+ }
+
@UnsupportedAppUsage
private final int jobId;
private final PersistableBundle extras;
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
index c90b872..175e5f2 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobSchedulerFrameworkInitializer.java
@@ -19,21 +19,14 @@
import android.app.JobSchedulerImpl;
import android.app.SystemServiceRegistry;
import android.content.Context;
-import android.os.BatteryStats;
/**
- * This class needs to be pre-loaded by zygote. This is where the job scheduler service wrapper
- * is registered.
- *
* @hide
*/
public class JobSchedulerFrameworkInitializer {
- static {
+ public static void initialize() {
SystemServiceRegistry.registerStaticService(
Context.JOB_SCHEDULER_SERVICE, JobScheduler.class,
(b) -> new JobSchedulerImpl(IJobScheduler.Stub.asInterface(b)));
-
- BatteryStats.setJobStopReasons(JobParameters.JOB_STOP_REASON_CODES,
- JobParameters::getReasonName);
}
}
diff --git a/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java b/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java
index e27670c..0568beb 100644
--- a/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java
+++ b/apex/jobscheduler/framework/java/android/os/DeviceIdleManager.java
@@ -84,4 +84,17 @@
return 0;
}
}
+
+ /**
+ * Return whether a given package is in the power-save whitelist or not.
+ * @hide
+ */
+ public boolean isApplicationWhitelisted(@NonNull String packageName) {
+ try {
+ return mService.isPowerSaveWhitelistApp(packageName);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return false;
+ }
+ }
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index a1734d8..4e96f5e 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -57,11 +57,10 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
-import android.os.ResultReceiver;
import android.os.ServiceManager;
-import android.os.ShellCallback;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManagerInternal;
@@ -899,7 +898,8 @@
}
final private IUidObserver mUidObserver = new IUidObserver.Stub() {
- @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
+ @Override public void onUidStateChanged(int uid, int procState, long procStateSeq,
+ int capability) {
mHandler.obtainMessage(MSG_UID_STATE_CHANGED, uid, procState).sendToTarget();
}
@@ -2689,12 +2689,15 @@
}
@Override
- public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
- (new JobSchedulerShellCommand(JobSchedulerService.this)).exec(
- this, in, out, err, args, callback, resultReceiver);
+ protected int handleShellCommand(@NonNull ParcelFileDescriptor in,
+ @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
+ @NonNull String[] args) {
+ return (new JobSchedulerShellCommand(JobSchedulerService.this)).exec(
+ this, in.getFileDescriptor(), out.getFileDescriptor(), err.getFileDescriptor(),
+ args);
}
+
/**
* <b>For internal system user only!</b>
* Returns a list of all currently-executing jobs.
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
index 01d158ba..a5c6c01 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java
@@ -20,13 +20,13 @@
import android.app.AppGlobals;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.os.BasicShellCommandHandler;
import android.os.Binder;
-import android.os.ShellCommand;
import android.os.UserHandle;
import java.io.PrintWriter;
-public final class JobSchedulerShellCommand extends ShellCommand {
+public final class JobSchedulerShellCommand extends BasicShellCommandHandler {
public static final int CMD_ERR_NO_PACKAGE = -1000;
public static final int CMD_ERR_NO_JOB = -1001;
public static final int CMD_ERR_CONSTRAINTS = -1002;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index cda5244..3aef5d1 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -466,7 +466,7 @@
private final IUidObserver mUidObserver = new IUidObserver.Stub() {
@Override
- public void onUidStateChanged(int uid, int procState, long procStateSeq) {
+ public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) {
mHandler.obtainMessage(MSG_UID_PROCESS_STATE_CHANGED, uid, procState).sendToTarget();
}
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index 5e5a04b..518a29c 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -583,7 +583,11 @@
} catch (IllegalArgumentException e) {
installer = "";
}
- sStatsd.informOnePackage(app, uid, pi.getLongVersionCode(), pi.versionName,
+ sStatsd.informOnePackage(
+ app,
+ uid,
+ pi.getLongVersionCode(),
+ pi.versionName == null ? "" : pi.versionName,
installer == null ? "" : installer);
}
} catch (Exception e) {
diff --git a/api/current.txt b/api/current.txt
index 57bbd77..e5acc40 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2827,7 +2827,7 @@
method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
method @NonNull public final android.accessibilityservice.AccessibilityButtonController getAccessibilityButtonController();
method @NonNull public final android.accessibilityservice.AccessibilityButtonController getAccessibilityButtonController(int);
- method @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) @NonNull public final android.accessibilityservice.FingerprintGestureController getFingerprintGestureController();
+ method @NonNull @RequiresPermission(android.Manifest.permission.USE_FINGERPRINT) public final android.accessibilityservice.FingerprintGestureController getFingerprintGestureController();
method @NonNull public final android.accessibilityservice.AccessibilityService.MagnificationController getMagnificationController();
method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
@@ -3541,11 +3541,11 @@
package android.annotation {
- @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface SuppressLint {
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) public @interface SuppressLint {
method public abstract String[] value();
}
- @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.FIELD}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface TargetApi {
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.FIELD}) public @interface TargetApi {
method public abstract int value();
}
@@ -3758,7 +3758,7 @@
method public void onContentChanged();
method public boolean onContextItemSelected(@NonNull android.view.MenuItem);
method public void onContextMenuClosed(@NonNull android.view.Menu);
- method @MainThread @CallSuper protected void onCreate(@Nullable android.os.Bundle);
+ method @CallSuper @MainThread protected void onCreate(@Nullable android.os.Bundle);
method public void onCreate(@Nullable android.os.Bundle, @Nullable android.os.PersistableBundle);
method public void onCreateContextMenu(android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo);
method @Nullable public CharSequence onCreateDescription();
@@ -3901,8 +3901,8 @@
method @Deprecated public void startActivityFromChild(@NonNull android.app.Activity, @RequiresPermission android.content.Intent, int, @Nullable android.os.Bundle);
method @Deprecated public void startActivityFromFragment(@NonNull android.app.Fragment, @RequiresPermission android.content.Intent, int);
method @Deprecated public void startActivityFromFragment(@NonNull android.app.Fragment, @RequiresPermission android.content.Intent, int, @Nullable android.os.Bundle);
- method public boolean startActivityIfNeeded(@RequiresPermission @NonNull android.content.Intent, int);
- method public boolean startActivityIfNeeded(@RequiresPermission @NonNull android.content.Intent, int, @Nullable android.os.Bundle);
+ method public boolean startActivityIfNeeded(@NonNull @RequiresPermission android.content.Intent, int);
+ method public boolean startActivityIfNeeded(@NonNull @RequiresPermission android.content.Intent, int, @Nullable android.os.Bundle);
method public void startIntentSenderForResult(android.content.IntentSender, int, @Nullable android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
method public void startIntentSenderForResult(android.content.IntentSender, int, @Nullable android.content.Intent, int, int, int, android.os.Bundle) throws android.content.IntentSender.SendIntentException;
method @Deprecated public void startIntentSenderFromChild(android.app.Activity, android.content.IntentSender, int, android.content.Intent, int, int, int) throws android.content.IntentSender.SendIntentException;
@@ -3910,8 +3910,8 @@
method public void startLocalVoiceInteraction(android.os.Bundle);
method public void startLockTask();
method @Deprecated public void startManagingCursor(android.database.Cursor);
- method public boolean startNextMatchingActivity(@RequiresPermission @NonNull android.content.Intent);
- method public boolean startNextMatchingActivity(@RequiresPermission @NonNull android.content.Intent, @Nullable android.os.Bundle);
+ method public boolean startNextMatchingActivity(@NonNull @RequiresPermission android.content.Intent);
+ method public boolean startNextMatchingActivity(@NonNull @RequiresPermission android.content.Intent, @Nullable android.os.Bundle);
method public void startPostponedEnterTransition();
method public void startSearch(@Nullable String, boolean, @Nullable android.os.Bundle, boolean);
method public void stopLocalVoiceInteraction();
@@ -6714,7 +6714,7 @@
method @NonNull public java.util.Set<java.lang.String> getAffiliationIds(@NonNull android.content.ComponentName);
method @Nullable public java.util.Set<java.lang.String> getAlwaysOnVpnLockdownWhitelist(@NonNull android.content.ComponentName);
method @Nullable public String getAlwaysOnVpnPackage(@NonNull android.content.ComponentName);
- method @WorkerThread @NonNull public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String);
+ method @NonNull @WorkerThread public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String);
method @Deprecated @Nullable public String getApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName);
method public boolean getAutoTimeRequired();
method @NonNull public java.util.List<android.os.UserHandle> getBindDeviceAdminTargetUsers(@NonNull android.content.ComponentName);
@@ -7640,7 +7640,7 @@
method public int checkSlicePermission(@NonNull android.net.Uri, int, int);
method @NonNull public java.util.List<android.net.Uri> getPinnedSlices();
method @NonNull public java.util.Set<android.app.slice.SliceSpec> getPinnedSpecs(android.net.Uri);
- method @WorkerThread @NonNull public java.util.Collection<android.net.Uri> getSliceDescendants(@NonNull android.net.Uri);
+ method @NonNull @WorkerThread public java.util.Collection<android.net.Uri> getSliceDescendants(@NonNull android.net.Uri);
method public void grantSlicePermission(@NonNull String, @NonNull android.net.Uri);
method @Nullable public android.net.Uri mapIntentToUri(@NonNull android.content.Intent);
method public void pinSlice(@NonNull android.net.Uri, @NonNull java.util.Set<android.app.slice.SliceSpec>);
@@ -7796,10 +7796,10 @@
public class StorageStatsManager {
method @WorkerThread public long getFreeBytes(@NonNull java.util.UUID) throws java.io.IOException;
method @WorkerThread public long getTotalBytes(@NonNull java.util.UUID) throws java.io.IOException;
- method @WorkerThread @NonNull public android.app.usage.ExternalStorageStats queryExternalStatsForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException;
- method @WorkerThread @NonNull public android.app.usage.StorageStats queryStatsForPackage(@NonNull java.util.UUID, @NonNull String, @NonNull android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
- method @WorkerThread @NonNull public android.app.usage.StorageStats queryStatsForUid(@NonNull java.util.UUID, int) throws java.io.IOException;
- method @WorkerThread @NonNull public android.app.usage.StorageStats queryStatsForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException;
+ method @NonNull @WorkerThread public android.app.usage.ExternalStorageStats queryExternalStatsForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException;
+ method @NonNull @WorkerThread public android.app.usage.StorageStats queryStatsForPackage(@NonNull java.util.UUID, @NonNull String, @NonNull android.os.UserHandle) throws java.io.IOException, android.content.pm.PackageManager.NameNotFoundException;
+ method @NonNull @WorkerThread public android.app.usage.StorageStats queryStatsForUid(@NonNull java.util.UUID, int) throws java.io.IOException;
+ method @NonNull @WorkerThread public android.app.usage.StorageStats queryStatsForUser(@NonNull java.util.UUID, @NonNull android.os.UserHandle) throws java.io.IOException;
}
public final class UsageEvents implements android.os.Parcelable {
@@ -8059,9 +8059,9 @@
method public boolean isMultipleAdvertisementSupported();
method public boolean isOffloadedFilteringSupported();
method public boolean isOffloadedScanBatchingSupported();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothServerSocket listenUsingInsecureL2capChannel() throws java.io.IOException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingInsecureL2capChannel() throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException;
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothServerSocket listenUsingL2capChannel() throws java.io.IOException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingL2capChannel() throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setName(String);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean startDiscovery();
@@ -8429,9 +8429,9 @@
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler);
method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean createBond();
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
- method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException;
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
method public int describeContents();
method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean fetchUuidsWithSdp();
@@ -9467,6 +9467,7 @@
method @NonNull public final android.content.ContentProvider.CallingIdentity clearCallingIdentity();
method public abstract int delete(@NonNull android.net.Uri, @Nullable String, @Nullable String[]);
method public void dump(java.io.FileDescriptor, java.io.PrintWriter, String[]);
+ method @Nullable public final String getCallingFeatureId();
method @Nullable public final String getCallingPackage();
method @Nullable public final android.content.Context getContext();
method @Nullable public final android.content.pm.PathPermission[] getPathPermissions();
@@ -9615,14 +9616,14 @@
method public static void addPeriodicSync(android.accounts.Account, String, android.os.Bundle, long);
method public static Object addStatusChangeListener(int, android.content.SyncStatusObserver);
method @NonNull public android.content.ContentProviderResult[] applyBatch(@NonNull String, @NonNull java.util.ArrayList<android.content.ContentProviderOperation>) throws android.content.OperationApplicationException, android.os.RemoteException;
- method public final int bulkInsert(@RequiresPermission.Write @NonNull android.net.Uri, @NonNull android.content.ContentValues[]);
+ method public final int bulkInsert(@NonNull @RequiresPermission.Write android.net.Uri, @NonNull android.content.ContentValues[]);
method @Nullable public final android.os.Bundle call(@NonNull android.net.Uri, @NonNull String, @Nullable String, @Nullable android.os.Bundle);
method @Nullable public final android.os.Bundle call(@NonNull String, @NonNull String, @Nullable String, @Nullable android.os.Bundle);
method @Deprecated public void cancelSync(android.net.Uri);
method public static void cancelSync(android.accounts.Account, String);
method public static void cancelSync(android.content.SyncRequest);
method @Nullable public final android.net.Uri canonicalize(@NonNull android.net.Uri);
- method public final int delete(@RequiresPermission.Write @NonNull android.net.Uri, @Nullable String, @Nullable String[]);
+ method public final int delete(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable String, @Nullable String[]);
method @Deprecated public static android.content.SyncInfo getCurrentSync();
method public static java.util.List<android.content.SyncInfo> getCurrentSyncs();
method public static int getIsSyncable(android.accounts.Account, String);
@@ -9635,7 +9636,7 @@
method public static boolean getSyncAutomatically(android.accounts.Account, String);
method @Nullable public final String getType(@NonNull android.net.Uri);
method @NonNull public final android.content.ContentResolver.MimeTypeInfo getTypeInfo(@NonNull String);
- method @Nullable public final android.net.Uri insert(@RequiresPermission.Write @NonNull android.net.Uri, @Nullable android.content.ContentValues);
+ method @Nullable public final android.net.Uri insert(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues);
method public static boolean isSyncActive(android.accounts.Account, String);
method public static boolean isSyncPending(android.accounts.Account, String);
method @NonNull public android.graphics.Bitmap loadThumbnail(@NonNull android.net.Uri, @NonNull android.util.Size, @Nullable android.os.CancellationSignal) throws java.io.IOException;
@@ -9654,9 +9655,9 @@
method @Nullable public final android.content.res.AssetFileDescriptor openTypedAssetFile(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException;
method @Nullable public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.Bundle) throws java.io.FileNotFoundException;
method @Nullable public final android.content.res.AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull android.net.Uri, @NonNull String, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal) throws java.io.FileNotFoundException;
- method @Nullable public final android.database.Cursor query(@RequiresPermission.Read @NonNull android.net.Uri, @Nullable String[], @Nullable String, @Nullable String[], @Nullable String);
- method @Nullable public final android.database.Cursor query(@RequiresPermission.Read @NonNull android.net.Uri, @Nullable String[], @Nullable String, @Nullable String[], @Nullable String, @Nullable android.os.CancellationSignal);
- method @Nullable public final android.database.Cursor query(@RequiresPermission.Read @NonNull android.net.Uri, @Nullable String[], @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal);
+ method @Nullable public final android.database.Cursor query(@NonNull @RequiresPermission.Read android.net.Uri, @Nullable String[], @Nullable String, @Nullable String[], @Nullable String);
+ method @Nullable public final android.database.Cursor query(@NonNull @RequiresPermission.Read android.net.Uri, @Nullable String[], @Nullable String, @Nullable String[], @Nullable String, @Nullable android.os.CancellationSignal);
+ method @Nullable public final android.database.Cursor query(@NonNull @RequiresPermission.Read android.net.Uri, @Nullable String[], @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal);
method public final boolean refresh(@NonNull android.net.Uri, @Nullable android.os.Bundle, @Nullable android.os.CancellationSignal);
method public final void registerContentObserver(@NonNull android.net.Uri, boolean, @NonNull android.database.ContentObserver);
method public void releasePersistableUriPermission(@NonNull android.net.Uri, int);
@@ -9671,7 +9672,7 @@
method public void takePersistableUriPermission(@NonNull android.net.Uri, int);
method @Nullable public final android.net.Uri uncanonicalize(@NonNull android.net.Uri);
method public final void unregisterContentObserver(@NonNull android.database.ContentObserver);
- method public final int update(@RequiresPermission.Write @NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]);
+ method public final int update(@NonNull @RequiresPermission.Write android.net.Uri, @Nullable android.content.ContentValues, @Nullable String, @Nullable String[]);
method public static void validateSyncExtrasBundle(android.os.Bundle);
method @NonNull public static android.content.ContentResolver wrap(@NonNull android.content.ContentProvider);
method @NonNull public static android.content.ContentResolver wrap(@NonNull android.content.ContentProviderClient);
@@ -9769,9 +9770,9 @@
public abstract class Context {
ctor public Context();
- method public boolean bindIsolatedService(@RequiresPermission @NonNull android.content.Intent, int, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.content.ServiceConnection);
+ method public boolean bindIsolatedService(@NonNull @RequiresPermission android.content.Intent, int, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.content.ServiceConnection);
method public abstract boolean bindService(@RequiresPermission android.content.Intent, @NonNull android.content.ServiceConnection, int);
- method public boolean bindService(@RequiresPermission @NonNull android.content.Intent, int, @NonNull java.util.concurrent.Executor, @NonNull android.content.ServiceConnection);
+ method public boolean bindService(@NonNull @RequiresPermission android.content.Intent, int, @NonNull java.util.concurrent.Executor, @NonNull android.content.ServiceConnection);
method @CheckResult(suggest="#enforceCallingOrSelfPermission(String,String)") public abstract int checkCallingOrSelfPermission(@NonNull String);
method @CheckResult(suggest="#enforceCallingOrSelfUriPermission(Uri,int,String)") public abstract int checkCallingOrSelfUriPermission(android.net.Uri, int);
method @CheckResult(suggest="#enforceCallingPermission(String,String)") public abstract int checkCallingPermission(@NonNull String);
@@ -9870,7 +9871,8 @@
method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS") public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle);
method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS") public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String);
method public abstract void sendOrderedBroadcast(@RequiresPermission android.content.Intent, @Nullable String);
- method public abstract void sendOrderedBroadcast(@RequiresPermission @NonNull android.content.Intent, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle);
+ method public abstract void sendOrderedBroadcast(@NonNull @RequiresPermission android.content.Intent, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle);
+ method public void sendOrderedBroadcast(@NonNull @RequiresPermission android.content.Intent, @Nullable String, @Nullable String, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle);
method @RequiresPermission("android.permission.INTERACT_ACROSS_USERS") public abstract void sendOrderedBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String, android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle);
method @Deprecated @RequiresPermission(android.Manifest.permission.BROADCAST_STICKY) public abstract void sendStickyBroadcast(@RequiresPermission android.content.Intent);
method @Deprecated @RequiresPermission(allOf={"android.permission.INTERACT_ACROSS_USERS", android.Manifest.permission.BROADCAST_STICKY}) public abstract void sendStickyBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle);
@@ -11724,7 +11726,7 @@
method @NonNull public abstract android.graphics.drawable.Drawable getUserBadgedDrawableForDensity(@NonNull android.graphics.drawable.Drawable, @NonNull android.os.UserHandle, @Nullable android.graphics.Rect, int);
method @NonNull public abstract android.graphics.drawable.Drawable getUserBadgedIcon(@NonNull android.graphics.drawable.Drawable, @NonNull android.os.UserHandle);
method @NonNull public abstract CharSequence getUserBadgedLabel(@NonNull CharSequence, @NonNull android.os.UserHandle);
- method @RequiresPermission(value="android.permission.WHITELIST_RESTRICTED_PERMISSIONS", conditional=true) @NonNull public java.util.Set<java.lang.String> getWhitelistedRestrictedPermissions(@NonNull String, int);
+ method @NonNull @RequiresPermission(value="android.permission.WHITELIST_RESTRICTED_PERMISSIONS", conditional=true) public java.util.Set<java.lang.String> getWhitelistedRestrictedPermissions(@NonNull String, int);
method @Nullable public abstract android.content.res.XmlResourceParser getXml(@NonNull String, @XmlRes int, @Nullable android.content.pm.ApplicationInfo);
method public boolean hasSigningCertificate(@NonNull String, @NonNull byte[], int);
method public boolean hasSigningCertificate(int, @NonNull byte[], int);
@@ -12418,7 +12420,7 @@
method public int addLoader(@NonNull android.content.res.loader.ResourceLoader, @NonNull android.content.res.loader.ResourcesProvider);
method public final void finishPreloading();
method public final void flushLayoutCache();
- method @NonNull public android.content.res.XmlResourceParser getAnimation(@AnimatorRes @AnimRes int) throws android.content.res.Resources.NotFoundException;
+ method @NonNull public android.content.res.XmlResourceParser getAnimation(@AnimRes @AnimatorRes int) throws android.content.res.Resources.NotFoundException;
method public final android.content.res.AssetManager getAssets();
method @AnyRes public static int getAttributeSetSourceResId(@Nullable android.util.AttributeSet);
method public boolean getBoolean(@BoolRes int) throws android.content.res.Resources.NotFoundException;
@@ -13724,10 +13726,10 @@
method public static android.graphics.Bitmap createBitmap(int, int, @NonNull android.graphics.Bitmap.Config, boolean, @NonNull android.graphics.ColorSpace);
method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, int, int, @NonNull android.graphics.Bitmap.Config, boolean);
method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, int, int, @NonNull android.graphics.Bitmap.Config, boolean, @NonNull android.graphics.ColorSpace);
- method public static android.graphics.Bitmap createBitmap(@NonNull @ColorInt int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config);
- method public static android.graphics.Bitmap createBitmap(@NonNull android.util.DisplayMetrics, @NonNull @ColorInt int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config);
- method public static android.graphics.Bitmap createBitmap(@NonNull @ColorInt int[], int, int, android.graphics.Bitmap.Config);
- method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, @NonNull @ColorInt int[], int, int, @NonNull android.graphics.Bitmap.Config);
+ method public static android.graphics.Bitmap createBitmap(@ColorInt @NonNull int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config);
+ method public static android.graphics.Bitmap createBitmap(@NonNull android.util.DisplayMetrics, @ColorInt @NonNull int[], int, int, int, int, @NonNull android.graphics.Bitmap.Config);
+ method public static android.graphics.Bitmap createBitmap(@ColorInt @NonNull int[], int, int, android.graphics.Bitmap.Config);
+ method public static android.graphics.Bitmap createBitmap(@Nullable android.util.DisplayMetrics, @ColorInt @NonNull int[], int, int, @NonNull android.graphics.Bitmap.Config);
method @NonNull public static android.graphics.Bitmap createBitmap(@NonNull android.graphics.Picture);
method @NonNull public static android.graphics.Bitmap createBitmap(@NonNull android.graphics.Picture, int, int, @NonNull android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createScaledBitmap(@NonNull android.graphics.Bitmap, int, int, boolean);
@@ -13960,8 +13962,8 @@
method public void drawDoubleRoundRect(@NonNull android.graphics.RectF, float, float, @NonNull android.graphics.RectF, float, float, @NonNull android.graphics.Paint);
method public void drawDoubleRoundRect(@NonNull android.graphics.RectF, @NonNull float[], @NonNull android.graphics.RectF, @NonNull float[], @NonNull android.graphics.Paint);
method public void drawLine(float, float, float, float, @NonNull android.graphics.Paint);
- method public void drawLines(@Size(multiple=4) @NonNull float[], int, int, @NonNull android.graphics.Paint);
- method public void drawLines(@Size(multiple=4) @NonNull float[], @NonNull android.graphics.Paint);
+ method public void drawLines(@NonNull @Size(multiple=4) float[], int, int, @NonNull android.graphics.Paint);
+ method public void drawLines(@NonNull @Size(multiple=4) float[], @NonNull android.graphics.Paint);
method public void drawOval(@NonNull android.graphics.RectF, @NonNull android.graphics.Paint);
method public void drawOval(float, float, float, float, @NonNull android.graphics.Paint);
method public void drawPaint(@NonNull android.graphics.Paint);
@@ -13971,7 +13973,7 @@
method public void drawPicture(@NonNull android.graphics.Picture, @NonNull android.graphics.Rect);
method public void drawPoint(float, float, @NonNull android.graphics.Paint);
method public void drawPoints(@Size(multiple=2) float[], int, int, @NonNull android.graphics.Paint);
- method public void drawPoints(@Size(multiple=2) @NonNull float[], @NonNull android.graphics.Paint);
+ method public void drawPoints(@NonNull @Size(multiple=2) float[], @NonNull android.graphics.Paint);
method @Deprecated public void drawPosText(@NonNull char[], int, int, @NonNull @Size(multiple=2) float[], @NonNull android.graphics.Paint);
method @Deprecated public void drawPosText(@NonNull String, @NonNull @Size(multiple=2) float[], @NonNull android.graphics.Paint);
method public void drawRGB(int, int, int);
@@ -14332,10 +14334,10 @@
method @AnyThread @NonNull public static android.graphics.ImageDecoder.Source createSource(@NonNull java.nio.ByteBuffer);
method @AnyThread @NonNull public static android.graphics.ImageDecoder.Source createSource(@NonNull java.io.File);
method @AnyThread @NonNull public static android.graphics.ImageDecoder.Source createSource(@NonNull java.util.concurrent.Callable<android.content.res.AssetFileDescriptor>);
- method @WorkerThread @NonNull public static android.graphics.Bitmap decodeBitmap(@NonNull android.graphics.ImageDecoder.Source, @NonNull android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException;
- method @WorkerThread @NonNull public static android.graphics.Bitmap decodeBitmap(@NonNull android.graphics.ImageDecoder.Source) throws java.io.IOException;
- method @WorkerThread @NonNull public static android.graphics.drawable.Drawable decodeDrawable(@NonNull android.graphics.ImageDecoder.Source, @NonNull android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException;
- method @WorkerThread @NonNull public static android.graphics.drawable.Drawable decodeDrawable(@NonNull android.graphics.ImageDecoder.Source) throws java.io.IOException;
+ method @NonNull @WorkerThread public static android.graphics.Bitmap decodeBitmap(@NonNull android.graphics.ImageDecoder.Source, @NonNull android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException;
+ method @NonNull @WorkerThread public static android.graphics.Bitmap decodeBitmap(@NonNull android.graphics.ImageDecoder.Source) throws java.io.IOException;
+ method @NonNull @WorkerThread public static android.graphics.drawable.Drawable decodeDrawable(@NonNull android.graphics.ImageDecoder.Source, @NonNull android.graphics.ImageDecoder.OnHeaderDecodedListener) throws java.io.IOException;
+ method @NonNull @WorkerThread public static android.graphics.drawable.Drawable decodeDrawable(@NonNull android.graphics.ImageDecoder.Source) throws java.io.IOException;
method public int getAllocator();
method @Nullable public android.graphics.Rect getCrop();
method public int getMemorySizePolicy();
@@ -14354,7 +14356,7 @@
method public void setPostProcessor(@Nullable android.graphics.PostProcessor);
method public void setTargetColorSpace(android.graphics.ColorSpace);
method public void setTargetSampleSize(@IntRange(from=1) int);
- method public void setTargetSize(@Px @IntRange(from=1) int, @Px @IntRange(from=1) int);
+ method public void setTargetSize(@IntRange(from=1) @Px int, @IntRange(from=1) @Px int);
method public void setUnpremultipliedRequired(boolean);
field public static final int ALLOCATOR_DEFAULT = 0; // 0x0
field public static final int ALLOCATOR_HARDWARE = 3; // 0x3
@@ -14461,8 +14463,8 @@
}
public class LinearGradient extends android.graphics.Shader {
- ctor public LinearGradient(float, float, float, float, @NonNull @ColorInt int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
- ctor public LinearGradient(float, float, float, float, @NonNull @ColorLong long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
+ ctor public LinearGradient(float, float, float, float, @ColorInt @NonNull int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
+ ctor public LinearGradient(float, float, float, float, @ColorLong @NonNull long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
ctor public LinearGradient(float, float, float, float, @ColorInt int, @ColorInt int, @NonNull android.graphics.Shader.TileMode);
ctor public LinearGradient(float, float, float, float, @ColorLong long, @ColorLong long, @NonNull android.graphics.Shader.TileMode);
}
@@ -15005,8 +15007,8 @@
}
public class RadialGradient extends android.graphics.Shader {
- ctor public RadialGradient(float, float, float, @NonNull @ColorInt int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
- ctor public RadialGradient(float, float, float, @NonNull @ColorLong long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
+ ctor public RadialGradient(float, float, float, @ColorInt @NonNull int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
+ ctor public RadialGradient(float, float, float, @ColorLong @NonNull long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
ctor public RadialGradient(float, float, float, @ColorInt int, @ColorInt int, @NonNull android.graphics.Shader.TileMode);
ctor public RadialGradient(float, float, float, @ColorLong long, @ColorLong long, @NonNull android.graphics.Shader.TileMode);
}
@@ -15264,8 +15266,8 @@
}
public class SweepGradient extends android.graphics.Shader {
- ctor public SweepGradient(float, float, @NonNull @ColorInt int[], @Nullable float[]);
- ctor public SweepGradient(float, float, @NonNull @ColorLong long[], @Nullable float[]);
+ ctor public SweepGradient(float, float, @ColorInt @NonNull int[], @Nullable float[]);
+ ctor public SweepGradient(float, float, @ColorLong @NonNull long[], @Nullable float[]);
ctor public SweepGradient(float, float, @ColorInt int, @ColorInt int);
ctor public SweepGradient(float, float, @ColorLong long, @ColorLong long);
}
@@ -15658,8 +15660,8 @@
method public void setColor(@ColorInt int);
method public void setColor(@Nullable android.content.res.ColorStateList);
method public void setColorFilter(@Nullable android.graphics.ColorFilter);
- method public void setColors(@Nullable @ColorInt int[]);
- method public void setColors(@Nullable @ColorInt int[], @Nullable float[]);
+ method public void setColors(@ColorInt @Nullable int[]);
+ method public void setColors(@ColorInt @Nullable int[], @Nullable float[]);
method public void setCornerRadii(@Nullable float[]);
method public void setCornerRadius(float);
method public void setDither(boolean);
@@ -16107,14 +16109,14 @@
public static class LineBreaker.ParagraphConstraints {
ctor public LineBreaker.ParagraphConstraints();
- method @Px @FloatRange(from=0) public float getDefaultTabStop();
- method @Px @FloatRange(from=0.0f) public float getFirstWidth();
- method @Px @IntRange(from=0) public int getFirstWidthLineCount();
+ method @FloatRange(from=0) @Px public float getDefaultTabStop();
+ method @FloatRange(from=0.0f) @Px public float getFirstWidth();
+ method @IntRange(from=0) @Px public int getFirstWidthLineCount();
method @Nullable public float[] getTabStops();
- method @Px @FloatRange(from=0.0f) public float getWidth();
- method public void setIndent(@Px @FloatRange(from=0.0f) float, @Px @IntRange(from=0) int);
- method public void setTabStops(@Nullable float[], @Px @FloatRange(from=0) float);
- method public void setWidth(@Px @FloatRange(from=0.0f) float);
+ method @FloatRange(from=0.0f) @Px public float getWidth();
+ method public void setIndent(@FloatRange(from=0.0f) @Px float, @IntRange(from=0) @Px int);
+ method public void setTabStops(@Nullable float[], @FloatRange(from=0) @Px float);
+ method public void setWidth(@FloatRange(from=0.0f) @Px float);
}
public static class LineBreaker.Result {
@@ -16137,7 +16139,7 @@
public static final class MeasuredText.Builder {
ctor public MeasuredText.Builder(@NonNull char[]);
ctor public MeasuredText.Builder(@NonNull android.graphics.text.MeasuredText);
- method @NonNull public android.graphics.text.MeasuredText.Builder appendReplacementRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, @Px @FloatRange(from=0) float);
+ method @NonNull public android.graphics.text.MeasuredText.Builder appendReplacementRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, @FloatRange(from=0) @Px float);
method @NonNull public android.graphics.text.MeasuredText.Builder appendStyleRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, boolean);
method @NonNull public android.graphics.text.MeasuredText build();
method @NonNull public android.graphics.text.MeasuredText.Builder setComputeHyphenation(boolean);
@@ -16858,6 +16860,7 @@
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.util.Rational> CONTROL_AE_COMPENSATION_STEP;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<java.lang.Boolean> CONTROL_AE_LOCK_AVAILABLE;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AF_AVAILABLE_MODES;
+ field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<android.hardware.camera2.params.CapabilityAndMaxSize[]> CONTROL_AVAILABLE_BOKEH_CAPABILITIES;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_EFFECTS;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_MODES;
field @NonNull public static final android.hardware.camera2.CameraCharacteristics.Key<int[]> CONTROL_AVAILABLE_SCENE_MODES;
@@ -17073,6 +17076,9 @@
field public static final int CONTROL_AWB_STATE_INACTIVE = 0; // 0x0
field public static final int CONTROL_AWB_STATE_LOCKED = 3; // 0x3
field public static final int CONTROL_AWB_STATE_SEARCHING = 1; // 0x1
+ field public static final int CONTROL_BOKEH_MODE_CONTINUOUS = 2; // 0x2
+ field public static final int CONTROL_BOKEH_MODE_OFF = 0; // 0x0
+ field public static final int CONTROL_BOKEH_MODE_STILL_CAPTURE = 1; // 0x1
field public static final int CONTROL_CAPTURE_INTENT_CUSTOM = 0; // 0x0
field public static final int CONTROL_CAPTURE_INTENT_MANUAL = 6; // 0x6
field public static final int CONTROL_CAPTURE_INTENT_MOTION_TRACKING = 7; // 0x7
@@ -17268,6 +17274,7 @@
field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Boolean> CONTROL_AWB_LOCK;
field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_AWB_MODE;
field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AWB_REGIONS;
+ field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_BOKEH_MODE;
field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_CAPTURE_INTENT;
field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Integer> CONTROL_EFFECT_MODE;
field @NonNull public static final android.hardware.camera2.CaptureRequest.Key<java.lang.Boolean> CONTROL_ENABLE_ZSL;
@@ -17353,6 +17360,7 @@
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_AWB_MODE;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<android.hardware.camera2.params.MeteringRectangle[]> CONTROL_AWB_REGIONS;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_AWB_STATE;
+ field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_BOKEH_MODE;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_CAPTURE_INTENT;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Integer> CONTROL_EFFECT_MODE;
field @NonNull public static final android.hardware.camera2.CaptureResult.Key<java.lang.Boolean> CONTROL_ENABLE_ZSL;
@@ -17449,6 +17457,11 @@
field public static final int COUNT = 4; // 0x4
}
+ public final class CapabilityAndMaxSize {
+ method @NonNull public android.util.Size getMaxStreamingSize();
+ method public int getMode();
+ }
+
public final class ColorSpaceTransform {
ctor public ColorSpaceTransform(android.util.Rational[]);
ctor public ColorSpaceTransform(int[]);
@@ -23156,7 +23169,7 @@
method @Nullable public String getGnssHardwareModelName();
method public int getGnssYearOfHardware();
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus);
- method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) @Nullable public android.location.Location getLastKnownLocation(@NonNull String);
+ method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String);
method @Nullable public android.location.LocationProvider getProvider(@NonNull String);
method @NonNull public java.util.List<java.lang.String> getProviders(boolean);
method @NonNull public java.util.List<java.lang.String> getProviders(@NonNull android.location.Criteria, boolean);
@@ -28627,17 +28640,17 @@
method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
method public boolean bindProcessToNetwork(@Nullable android.net.Network);
method @NonNull public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull android.net.IpSecManager.UdpEncapsulationSocket, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
- method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @Nullable public android.net.Network getActiveNetwork();
+ method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network getActiveNetwork();
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getActiveNetworkInfo();
method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo[] getAllNetworkInfo();
- method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @NonNull public android.net.Network[] getAllNetworks();
+ method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network[] getAllNetworks();
method @Deprecated public boolean getBackgroundDataSetting();
method @Nullable public android.net.Network getBoundNetworkForProcess();
method public int getConnectionOwnerUid(int, @NonNull java.net.InetSocketAddress, @NonNull java.net.InetSocketAddress);
method @Nullable public android.net.ProxyInfo getDefaultProxy();
- method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @Nullable public android.net.LinkProperties getLinkProperties(@Nullable android.net.Network);
+ method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.LinkProperties getLinkProperties(@Nullable android.net.Network);
method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getMultipathPreference(@Nullable android.net.Network);
- method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) @Nullable public android.net.NetworkCapabilities getNetworkCapabilities(@Nullable android.net.Network);
+ method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkCapabilities getNetworkCapabilities(@Nullable android.net.Network);
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(int);
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getNetworkInfo(@Nullable android.net.Network);
method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public int getNetworkPreference();
@@ -29773,6 +29786,7 @@
public class ScanResult implements android.os.Parcelable {
method public int describeContents();
+ method public int getWifiStandard();
method public boolean is80211mcResponder();
method public boolean isPasspointNetwork();
method public void writeToParcel(android.os.Parcel, int);
@@ -29783,6 +29797,11 @@
field public static final int CHANNEL_WIDTH_80MHZ = 2; // 0x2
field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; // 0x4
field public String SSID;
+ field public static final int WIFI_STANDARD_11AC = 5; // 0x5
+ field public static final int WIFI_STANDARD_11AX = 6; // 0x6
+ field public static final int WIFI_STANDARD_11N = 4; // 0x4
+ field public static final int WIFI_STANDARD_LEGACY = 1; // 0x1
+ field public static final int WIFI_STANDARD_UNKNOWN = 0; // 0x0
field public String capabilities;
field public int centerFreq0;
field public int centerFreq1;
@@ -29979,16 +29998,11 @@
method public String getSSID();
method public android.net.wifi.SupplicantState getSupplicantState();
method @IntRange(from=0xffffffff) public int getTxLinkSpeedMbps();
- method public int getWifiTechnology();
+ method public int getWifiStandard();
method public void writeToParcel(android.os.Parcel, int);
field public static final String FREQUENCY_UNITS = "MHz";
field public static final String LINK_SPEED_UNITS = "Mbps";
field public static final int LINK_SPEED_UNKNOWN = -1; // 0xffffffff
- field public static final int WIFI_TECHNOLOGY_11AC = 5; // 0x5
- field public static final int WIFI_TECHNOLOGY_11AX = 6; // 0x6
- field public static final int WIFI_TECHNOLOGY_11N = 4; // 0x4
- field public static final int WIFI_TECHNOLOGY_LEGACY = 1; // 0x1
- field public static final int WIFI_TECHNOLOGY_UNKNOWN = 0; // 0x0
}
public class WifiManager {
@@ -30009,7 +30023,7 @@
method public android.net.wifi.WifiInfo getConnectionInfo();
method public android.net.DhcpInfo getDhcpInfo();
method public int getMaxNumberOfNetworkSuggestionsPerApp();
- method @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) @NonNull public java.util.List<android.net.wifi.WifiNetworkSuggestion> getNetworkSuggestions();
+ method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE) public java.util.List<android.net.wifi.WifiNetworkSuggestion> getNetworkSuggestions();
method @Deprecated @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", "android.permission.NETWORK_SETUP_WIZARD"}) public java.util.List<android.net.wifi.hotspot2.PasspointConfiguration> getPasspointConfigurations();
method public java.util.List<android.net.wifi.ScanResult> getScanResults();
method public int getWifiState();
@@ -30036,7 +30050,7 @@
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(String, boolean);
method @Deprecated public boolean setWifiEnabled(boolean);
- method public void startLocalOnlyHotspot(android.net.wifi.WifiManager.LocalOnlyHotspotCallback, @Nullable android.os.Handler);
+ method @RequiresPermission(allOf={android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void startLocalOnlyHotspot(android.net.wifi.WifiManager.LocalOnlyHotspotCallback, @Nullable android.os.Handler);
method @Deprecated public boolean startScan();
method @Deprecated public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback);
method @Deprecated public int updateNetwork(android.net.wifi.WifiConfiguration);
@@ -30960,10 +30974,10 @@
method public boolean isDefaultServiceForCategory(android.content.ComponentName, String);
method public boolean registerAidsForService(android.content.ComponentName, String, java.util.List<java.lang.String>);
method public boolean removeAidsForService(android.content.ComponentName, String);
- method @RequiresPermission(android.Manifest.permission.NFC) @NonNull public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String);
+ method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String);
method public boolean setPreferredService(android.app.Activity, android.content.ComponentName);
method public boolean supportsAidPrefixRegistration();
- method @RequiresPermission(android.Manifest.permission.NFC) @NonNull public boolean unsetOffHostForService(@NonNull android.content.ComponentName);
+ method @NonNull @RequiresPermission(android.Manifest.permission.NFC) public boolean unsetOffHostForService(@NonNull android.content.ComponentName);
method public boolean unsetPreferredService(android.app.Activity);
field public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
field public static final String CATEGORY_OTHER = "other";
@@ -34619,7 +34633,7 @@
method public void addData(String, byte[], int);
method public void addFile(String, java.io.File, int) throws java.io.IOException;
method public void addText(String, String);
- method @RequiresPermission(allOf={android.Manifest.permission.READ_LOGS, android.Manifest.permission.PACKAGE_USAGE_STATS}) @Nullable public android.os.DropBoxManager.Entry getNextEntry(String, long);
+ method @Nullable @RequiresPermission(allOf={android.Manifest.permission.READ_LOGS, android.Manifest.permission.PACKAGE_USAGE_STATS}) public android.os.DropBoxManager.Entry getNextEntry(String, long);
method public boolean isTagEnabled(String);
field public static final String ACTION_DROPBOX_ENTRY_ADDED = "android.intent.action.DROPBOX_ENTRY_ADDED";
field public static final String EXTRA_DROPPED_COUNT = "android.os.extra.DROPPED_COUNT";
@@ -35505,7 +35519,7 @@
method public String getUserName();
method public java.util.List<android.os.UserHandle> getUserProfiles();
method public android.os.Bundle getUserRestrictions();
- method public android.os.Bundle getUserRestrictions(android.os.UserHandle);
+ method @RequiresPermission(anyOf={"android.permission.MANAGE_USERS", "android.permission.INTERACT_ACROSS_USERS"}, conditional=true) public android.os.Bundle getUserRestrictions(android.os.UserHandle);
method public boolean hasUserRestriction(String);
method public boolean isDemoUser();
method public boolean isQuietModeEnabled(android.os.UserHandle);
@@ -38490,7 +38504,11 @@
method @NonNull public static String getVersion(@NonNull android.content.Context, @NonNull String);
method @NonNull public static String getVolumeName(@NonNull android.net.Uri);
method @NonNull public static android.net.Uri setIncludePending(@NonNull android.net.Uri);
+ method @NonNull public static android.net.Uri setIncludeTrashed(@NonNull android.net.Uri);
method @NonNull public static android.net.Uri setRequireOriginal(@NonNull android.net.Uri);
+ method public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri);
+ method public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri, long);
+ method public static void untrash(@NonNull android.content.Context, @NonNull android.net.Uri);
field public static final String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
field public static final String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE";
field public static final String ACTION_REVIEW = "android.provider.action.REVIEW";
@@ -38583,14 +38601,11 @@
}
public static interface MediaStore.Audio.AudioColumns extends android.provider.MediaStore.MediaColumns {
- field public static final String ALBUM = "album";
field public static final String ALBUM_ID = "album_id";
field @Deprecated public static final String ALBUM_KEY = "album_key";
- field public static final String ARTIST = "artist";
field public static final String ARTIST_ID = "artist_id";
field @Deprecated public static final String ARTIST_KEY = "artist_key";
field public static final String BOOKMARK = "bookmark";
- field public static final String COMPOSER = "composer";
field public static final String GENRE = "genre";
field public static final String GENRE_ID = "genre_id";
field @Deprecated public static final String GENRE_KEY = "genre_key";
@@ -38705,7 +38720,6 @@
field public static final int MEDIA_TYPE_VIDEO = 3; // 0x3
field public static final String MIME_TYPE = "mime_type";
field public static final String PARENT = "parent";
- field public static final String TITLE = "title";
}
public static final class MediaStore.Images {
@@ -38714,6 +38728,9 @@
public static interface MediaStore.Images.ImageColumns extends android.provider.MediaStore.MediaColumns {
field public static final String DESCRIPTION = "description";
+ field public static final String EXPOSURE_TIME = "exposure_time";
+ field public static final String F_NUMBER = "f_number";
+ field public static final String ISO = "iso";
field public static final String IS_PRIVATE = "isprivate";
field @Deprecated public static final String LATITUDE = "latitude";
field @Deprecated public static final String LONGITUDE = "longitude";
@@ -38762,28 +38779,45 @@
}
public static interface MediaStore.MediaColumns extends android.provider.BaseColumns {
+ field public static final String ALBUM = "album";
+ field public static final String ALBUM_ARTIST = "album_artist";
+ field public static final String ARTIST = "artist";
+ field public static final String AUTHOR = "author";
+ field public static final String BITRATE = "bitrate";
field public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
field public static final String BUCKET_ID = "bucket_id";
+ field public static final String CAPTURE_FRAMERATE = "capture_framerate";
+ field public static final String CD_TRACK_NUMBER = "cd_track_number";
+ field public static final String COMPILATION = "compilation";
+ field public static final String COMPOSER = "composer";
field @Deprecated public static final String DATA = "_data";
field public static final String DATE_ADDED = "date_added";
field public static final String DATE_EXPIRES = "date_expires";
field public static final String DATE_MODIFIED = "date_modified";
field public static final String DATE_TAKEN = "datetaken";
+ field public static final String DISC_NUMBER = "disc_number";
field public static final String DISPLAY_NAME = "_display_name";
field public static final String DOCUMENT_ID = "document_id";
field public static final String DURATION = "duration";
+ field public static final String GENRE = "genre";
field public static final String HEIGHT = "height";
field public static final String INSTANCE_ID = "instance_id";
+ field public static final String IS_FAVORITE = "is_favorite";
field public static final String IS_PENDING = "is_pending";
+ field public static final String IS_TRASHED = "is_trashed";
field public static final String MIME_TYPE = "mime_type";
+ field public static final String NUM_TRACKS = "num_tracks";
field public static final String ORIENTATION = "orientation";
field public static final String ORIGINAL_DOCUMENT_ID = "original_document_id";
field public static final String OWNER_PACKAGE_NAME = "owner_package_name";
field public static final String RELATIVE_PATH = "relative_path";
+ field public static final String RESOLUTION = "resolution";
field public static final String SIZE = "_size";
field public static final String TITLE = "title";
field public static final String VOLUME_NAME = "volume_name";
field public static final String WIDTH = "width";
+ field public static final String WRITER = "writer";
+ field public static final String YEAR = "year";
}
public static final class MediaStore.Video {
@@ -38823,8 +38857,6 @@
}
public static interface MediaStore.Video.VideoColumns extends android.provider.MediaStore.MediaColumns {
- field public static final String ALBUM = "album";
- field public static final String ARTIST = "artist";
field public static final String BOOKMARK = "bookmark";
field public static final String CATEGORY = "category";
field public static final String COLOR_RANGE = "color_range";
@@ -38836,7 +38868,6 @@
field @Deprecated public static final String LATITUDE = "latitude";
field @Deprecated public static final String LONGITUDE = "longitude";
field @Deprecated public static final String MINI_THUMB_MAGIC = "mini_thumb_magic";
- field public static final String RESOLUTION = "resolution";
field public static final String TAGS = "tags";
}
@@ -42885,6 +42916,7 @@
field public static final int IP_MULTICAST_TTL;
field public static final int IP_TOS;
field public static final int IP_TTL;
+ field public static final int MAP_ANONYMOUS;
field public static final int MAP_FIXED;
field public static final int MAP_PRIVATE;
field public static final int MAP_SHARED;
@@ -44019,7 +44051,7 @@
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telecom.PhoneAccountHandle> getSelfManagedPhoneAccounts();
method public android.telecom.PhoneAccountHandle getSimCallManager();
method @Nullable public String getSystemDialerPackage();
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @Nullable public android.telecom.PhoneAccountHandle getUserSelectedOutgoingPhoneAccount();
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telecom.PhoneAccountHandle getUserSelectedOutgoingPhoneAccount();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailNumber(android.telecom.PhoneAccountHandle);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handleMmi(String);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean handleMmi(String, android.telecom.PhoneAccountHandle);
@@ -44380,6 +44412,7 @@
field public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSRP_INT = "opportunistic_network_exit_threshold_rsrp_int";
field public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_RSSNR_INT = "opportunistic_network_exit_threshold_rssnr_int";
field public static final String KEY_PREFER_2G_BOOL = "prefer_2g_bool";
+ field public static final String KEY_PREVENT_CLIR_ACTIVATION_AND_DEACTIVATION_CODE_BOOL = "prevent_clir_activation_and_deactivation_code_bool";
field public static final String KEY_RADIO_RESTART_FAILURE_CAUSES_INT_ARRAY = "radio_restart_failure_causes_int_array";
field public static final String KEY_RCS_CONFIG_SERVER_URL_STRING = "rcs_config_server_url_string";
field public static final String KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL = "require_entitlement_checks_bool";
@@ -44947,6 +44980,7 @@
method public static int getDefaultSmsSubscriptionId();
method public static android.telephony.SmsManager getSmsManagerForSubscriptionId(int);
method @RequiresPermission(android.Manifest.permission.SMS_FINANCIAL_TRANSACTIONS) public void getSmsMessagesForFinancialApp(android.os.Bundle, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.SmsManager.FinancialSmsCallback);
+ method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSmscAddress();
method public int getSubscriptionId();
method public void injectSmsPdu(byte[], String, android.app.PendingIntent);
method public void sendDataMessage(String, String, short, byte[], android.app.PendingIntent, android.app.PendingIntent);
@@ -44954,6 +44988,7 @@
method public void sendMultipartTextMessage(String, String, java.util.ArrayList<java.lang.String>, java.util.ArrayList<android.app.PendingIntent>, java.util.ArrayList<android.app.PendingIntent>);
method public void sendTextMessage(String, String, String, android.app.PendingIntent, android.app.PendingIntent);
method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.SEND_SMS}) public void sendTextMessageWithoutPersisting(String, String, String, android.app.PendingIntent, android.app.PendingIntent);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSmscAddress(@NonNull String);
field public static final String EXTRA_MMS_DATA = "android.telephony.extra.MMS_DATA";
field public static final String EXTRA_MMS_HTTP_STATUS = "android.telephony.extra.MMS_HTTP_STATUS";
field public static final String MMS_CONFIG_ALIAS_ENABLED = "aliasEnabled";
@@ -45254,9 +45289,9 @@
method public int getDataState();
method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDeviceId();
method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getDeviceId(int);
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @Nullable public String getDeviceSoftwareVersion();
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @NonNull public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList();
- method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) @NonNull public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList(int);
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getDeviceSoftwareVersion();
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList();
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>> getEmergencyNumberList(int);
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String[] getForbiddenPlmns();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getGroupIdLevel1();
method public String getIccAuthentication(int, int, String);
@@ -45290,11 +45325,12 @@
method @Nullable public CharSequence getSimSpecificCarrierIdName();
method public int getSimState();
method public int getSimState(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getSubIdForPhoneAccountHandle(@NonNull android.telecom.PhoneAccountHandle);
method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getSubscriberId();
method public int getSupportedModemCount();
method @Nullable public String getTypeAllocationCode();
method @Nullable public String getTypeAllocationCode(int);
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @NonNull public java.util.List<android.telephony.UiccCardInfo> getUiccCardsInfo();
+ method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public java.util.List<android.telephony.UiccCardInfo> getUiccCardsInfo();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVisualVoicemailPackageName();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailAlphaTag();
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getVoiceMailNumber();
@@ -47228,7 +47264,7 @@
}
public static class LineHeightSpan.Standard implements android.text.style.LineHeightSpan android.text.ParcelableSpan {
- ctor public LineHeightSpan.Standard(@Px @IntRange(from=1) int);
+ ctor public LineHeightSpan.Standard(@IntRange(from=1) @Px int);
ctor public LineHeightSpan.Standard(@NonNull android.os.Parcel);
method public void chooseHeight(@NonNull CharSequence, int, int, int, int, @NonNull android.graphics.Paint.FontMetricsInt);
method public int describeContents();
@@ -49159,6 +49195,7 @@
public class HapticFeedbackConstants {
field public static final int CLOCK_TICK = 4; // 0x4
+ field public static final int CONFIRM = 16; // 0x10
field public static final int CONTEXT_CLICK = 6; // 0x6
field public static final int FLAG_IGNORE_GLOBAL_SETTING = 2; // 0x2
field public static final int FLAG_IGNORE_VIEW_SETTING = 1; // 0x1
@@ -49166,6 +49203,7 @@
field public static final int KEYBOARD_RELEASE = 7; // 0x7
field public static final int KEYBOARD_TAP = 3; // 0x3
field public static final int LONG_PRESS = 0; // 0x0
+ field public static final int REJECT = 17; // 0x11
field public static final int TEXT_HANDLE_MOVE = 9; // 0x9
field public static final int VIRTUAL_KEY = 1; // 0x1
field public static final int VIRTUAL_KEY_RELEASE = 8; // 0x8
@@ -50353,34 +50391,34 @@
}
public class TextureView extends android.view.View {
- ctor public TextureView(android.content.Context);
- ctor public TextureView(android.content.Context, android.util.AttributeSet);
- ctor public TextureView(android.content.Context, android.util.AttributeSet, int);
- ctor public TextureView(android.content.Context, android.util.AttributeSet, int, int);
+ ctor public TextureView(@NonNull android.content.Context);
+ ctor public TextureView(@NonNull android.content.Context, @Nullable android.util.AttributeSet);
+ ctor public TextureView(@NonNull android.content.Context, @Nullable android.util.AttributeSet, int);
+ ctor public TextureView(@NonNull android.content.Context, @Nullable android.util.AttributeSet, int, int);
method public final void draw(android.graphics.Canvas);
- method public android.graphics.Bitmap getBitmap();
- method public android.graphics.Bitmap getBitmap(int, int);
- method public android.graphics.Bitmap getBitmap(android.graphics.Bitmap);
- method public android.graphics.SurfaceTexture getSurfaceTexture();
- method public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener();
- method public android.graphics.Matrix getTransform(android.graphics.Matrix);
+ method @Nullable public android.graphics.Bitmap getBitmap();
+ method @Nullable public android.graphics.Bitmap getBitmap(int, int);
+ method @NonNull public android.graphics.Bitmap getBitmap(@NonNull android.graphics.Bitmap);
+ method @Nullable public android.graphics.SurfaceTexture getSurfaceTexture();
+ method @Nullable public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener();
+ method @NonNull public android.graphics.Matrix getTransform(@Nullable android.graphics.Matrix);
method public boolean isAvailable();
- method public android.graphics.Canvas lockCanvas();
- method public android.graphics.Canvas lockCanvas(android.graphics.Rect);
+ method @Nullable public android.graphics.Canvas lockCanvas();
+ method @Nullable public android.graphics.Canvas lockCanvas(@Nullable android.graphics.Rect);
method protected final void onDraw(android.graphics.Canvas);
method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
method public void setOpaque(boolean);
- method public void setSurfaceTexture(android.graphics.SurfaceTexture);
- method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener);
- method public void setTransform(android.graphics.Matrix);
- method public void unlockCanvasAndPost(android.graphics.Canvas);
+ method public void setSurfaceTexture(@NonNull android.graphics.SurfaceTexture);
+ method public void setSurfaceTextureListener(@Nullable android.view.TextureView.SurfaceTextureListener);
+ method public void setTransform(@Nullable android.graphics.Matrix);
+ method public void unlockCanvasAndPost(@NonNull android.graphics.Canvas);
}
public static interface TextureView.SurfaceTextureListener {
- method public void onSurfaceTextureAvailable(android.graphics.SurfaceTexture, int, int);
- method public boolean onSurfaceTextureDestroyed(android.graphics.SurfaceTexture);
- method public void onSurfaceTextureSizeChanged(android.graphics.SurfaceTexture, int, int);
- method public void onSurfaceTextureUpdated(android.graphics.SurfaceTexture);
+ method public void onSurfaceTextureAvailable(@NonNull android.graphics.SurfaceTexture, int, int);
+ method public boolean onSurfaceTextureDestroyed(@NonNull android.graphics.SurfaceTexture);
+ method public void onSurfaceTextureSizeChanged(@NonNull android.graphics.SurfaceTexture, int, int);
+ method public void onSurfaceTextureUpdated(@NonNull android.graphics.SurfaceTexture);
}
public class TouchDelegate {
@@ -50640,7 +50678,7 @@
method public final int getScrollY();
method @android.view.ViewDebug.ExportedProperty(category="drawing") @ColorInt public int getSolidColor();
method @LayoutRes public int getSourceLayoutResId();
- method @android.view.ViewDebug.ExportedProperty(category="accessibility") @Nullable public final CharSequence getStateDescription();
+ method @android.view.ViewDebug.ExportedProperty(category="accessibility") @Nullable public CharSequence getStateDescription();
method public android.animation.StateListAnimator getStateListAnimator();
method protected int getSuggestedMinimumHeight();
method protected int getSuggestedMinimumWidth();
@@ -51374,11 +51412,11 @@
field @Deprecated public static final boolean TRACE_RECYCLER = false;
}
- @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public static @interface ViewDebug.CapturedViewProperty {
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD}) public static @interface ViewDebug.CapturedViewProperty {
method public abstract boolean retrieveReturn() default false;
}
- @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public static @interface ViewDebug.ExportedProperty {
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD}) public static @interface ViewDebug.ExportedProperty {
method public abstract String category() default "";
method public abstract boolean deepExport() default false;
method public abstract android.view.ViewDebug.FlagToString[] flagMapping() default {};
@@ -51390,7 +51428,7 @@
method public abstract boolean resolveId() default false;
}
- @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public static @interface ViewDebug.FlagToString {
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) public static @interface ViewDebug.FlagToString {
method public abstract int equals();
method public abstract int mask();
method public abstract String name();
@@ -51408,7 +51446,7 @@
enum_constant @Deprecated public static final android.view.ViewDebug.HierarchyTraceType REQUEST_LAYOUT;
}
- @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public static @interface ViewDebug.IntToString {
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) public static @interface ViewDebug.IntToString {
method public abstract int from();
method public abstract String to();
}
@@ -53966,18 +54004,18 @@
}
public interface TextClassifier {
- method @WorkerThread @NonNull public default android.view.textclassifier.TextClassification classifyText(@NonNull android.view.textclassifier.TextClassification.Request);
- method @WorkerThread @NonNull public default android.view.textclassifier.TextClassification classifyText(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @Nullable android.os.LocaleList);
+ method @NonNull @WorkerThread public default android.view.textclassifier.TextClassification classifyText(@NonNull android.view.textclassifier.TextClassification.Request);
+ method @NonNull @WorkerThread public default android.view.textclassifier.TextClassification classifyText(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @Nullable android.os.LocaleList);
method public default void destroy();
- method @WorkerThread @NonNull public default android.view.textclassifier.TextLanguage detectLanguage(@NonNull android.view.textclassifier.TextLanguage.Request);
- method @WorkerThread @NonNull public default android.view.textclassifier.TextLinks generateLinks(@NonNull android.view.textclassifier.TextLinks.Request);
+ method @NonNull @WorkerThread public default android.view.textclassifier.TextLanguage detectLanguage(@NonNull android.view.textclassifier.TextLanguage.Request);
+ method @NonNull @WorkerThread public default android.view.textclassifier.TextLinks generateLinks(@NonNull android.view.textclassifier.TextLinks.Request);
method @WorkerThread public default int getMaxGenerateLinksTextLength();
method public default boolean isDestroyed();
method public default void onSelectionEvent(@NonNull android.view.textclassifier.SelectionEvent);
method public default void onTextClassifierEvent(@NonNull android.view.textclassifier.TextClassifierEvent);
- method @WorkerThread @NonNull public default android.view.textclassifier.ConversationActions suggestConversationActions(@NonNull android.view.textclassifier.ConversationActions.Request);
- method @WorkerThread @NonNull public default android.view.textclassifier.TextSelection suggestSelection(@NonNull android.view.textclassifier.TextSelection.Request);
- method @WorkerThread @NonNull public default android.view.textclassifier.TextSelection suggestSelection(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @Nullable android.os.LocaleList);
+ method @NonNull @WorkerThread public default android.view.textclassifier.ConversationActions suggestConversationActions(@NonNull android.view.textclassifier.ConversationActions.Request);
+ method @NonNull @WorkerThread public default android.view.textclassifier.TextSelection suggestSelection(@NonNull android.view.textclassifier.TextSelection.Request);
+ method @NonNull @WorkerThread public default android.view.textclassifier.TextSelection suggestSelection(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @Nullable android.os.LocaleList);
field public static final String EXTRA_FROM_TEXT_CLASSIFIER = "android.view.textclassifier.extra.FROM_TEXT_CLASSIFIER";
field public static final String HINT_TEXT_IS_EDITABLE = "android.text_is_editable";
field public static final String HINT_TEXT_IS_NOT_EDITABLE = "android.text_is_not_editable";
@@ -56441,12 +56479,12 @@
ctor public Magnifier.Builder(@NonNull android.view.View);
method @NonNull public android.widget.Magnifier build();
method @NonNull public android.widget.Magnifier.Builder setClippingEnabled(boolean);
- method @NonNull public android.widget.Magnifier.Builder setCornerRadius(@Px @FloatRange(from=0) float);
+ method @NonNull public android.widget.Magnifier.Builder setCornerRadius(@FloatRange(from=0) @Px float);
method @NonNull public android.widget.Magnifier.Builder setDefaultSourceToMagnifierOffset(@Px int, @Px int);
- method @NonNull public android.widget.Magnifier.Builder setElevation(@Px @FloatRange(from=0) float);
+ method @NonNull public android.widget.Magnifier.Builder setElevation(@FloatRange(from=0) @Px float);
method @NonNull public android.widget.Magnifier.Builder setInitialZoom(@FloatRange(from=0.0f) float);
method @NonNull public android.widget.Magnifier.Builder setOverlay(@Nullable android.graphics.drawable.Drawable);
- method @NonNull public android.widget.Magnifier.Builder setSize(@Px @IntRange(from=0) int, @Px @IntRange(from=0) int);
+ method @NonNull public android.widget.Magnifier.Builder setSize(@IntRange(from=0) @Px int, @IntRange(from=0) @Px int);
method @NonNull public android.widget.Magnifier.Builder setSourceBounds(int, int, int, int);
}
@@ -56940,7 +56978,7 @@
method @NonNull public static android.widget.RemoteViews.RemoteResponse fromPendingIntent(@NonNull android.app.PendingIntent);
}
- @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) public static @interface RemoteViews.RemoteView {
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE}) public static @interface RemoteViews.RemoteView {
}
public abstract class RemoteViewsService extends android.app.Service {
@@ -57617,7 +57655,7 @@
method public void setExtractedText(android.view.inputmethod.ExtractedText);
method public void setFallbackLineSpacing(boolean);
method public void setFilters(android.text.InputFilter[]);
- method public void setFirstBaselineToTopHeight(@Px @IntRange(from=0) int);
+ method public void setFirstBaselineToTopHeight(@IntRange(from=0) @Px int);
method public void setFontFeatureSettings(@Nullable String);
method public boolean setFontVariationSettings(@Nullable String);
method protected boolean setFrame(int, int, int, int);
@@ -57639,9 +57677,9 @@
method public void setInputType(int);
method public void setJustificationMode(int);
method public void setKeyListener(android.text.method.KeyListener);
- method public void setLastBaselineToBottomHeight(@Px @IntRange(from=0) int);
+ method public void setLastBaselineToBottomHeight(@IntRange(from=0) @Px int);
method public void setLetterSpacing(float);
- method public void setLineHeight(@Px @IntRange(from=0) int);
+ method public void setLineHeight(@IntRange(from=0) @Px int);
method public void setLineSpacing(float, float);
method public void setLines(int);
method public final void setLinkTextColor(@ColorInt int);
@@ -60696,7 +60734,7 @@
ctor public OutOfMemoryError(String);
}
- @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public @interface Override {
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target(java.lang.annotation.ElementType.METHOD) public @interface Override {
}
public class Package implements java.lang.reflect.AnnotatedElement {
@@ -61188,9 +61226,9 @@
method @NonNull public StringBuilder reverse();
method public void setCharAt(int, char);
method public void setLength(int);
- method public CharSequence subSequence(int, int);
- method public String substring(int);
- method public String substring(int, int);
+ method @NonNull public CharSequence subSequence(int, int);
+ method @NonNull public String substring(int);
+ method @NonNull public String substring(int, int);
method public void trimToSize();
}
@@ -61200,7 +61238,7 @@
ctor public StringIndexOutOfBoundsException(int);
}
- @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public @interface SuppressWarnings {
+ @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) public @interface SuppressWarnings {
method public abstract String[] value();
}
@@ -71523,20 +71561,20 @@
method public boolean addAll(@NonNull java.util.Collection<? extends K>);
method public final void clear();
method public boolean contains(@NonNull Object);
- method public final boolean containsAll(java.util.Collection<?>);
+ method public final boolean containsAll(@NonNull java.util.Collection<?>);
method public void forEach(@NonNull java.util.function.Consumer<? super K>);
- method public java.util.concurrent.ConcurrentHashMap<K,V> getMap();
+ method @NonNull public java.util.concurrent.ConcurrentHashMap<K,V> getMap();
method @Nullable public V getMappedValue();
method public final boolean isEmpty();
method @NonNull public java.util.Iterator<K> iterator();
method public boolean remove(@NonNull Object);
- method public final boolean removeAll(java.util.Collection<?>);
- method public final boolean retainAll(java.util.Collection<?>);
+ method public final boolean removeAll(@NonNull java.util.Collection<?>);
+ method public final boolean retainAll(@NonNull java.util.Collection<?>);
method public final int size();
method @NonNull public java.util.Spliterator<K> spliterator();
- method public final Object[] toArray();
- method public final <T> T[] toArray(T[]);
- method public final String toString();
+ method @NonNull public final Object[] toArray();
+ method @NonNull public final <T> T[] toArray(@NonNull T[]);
+ method @NonNull public final String toString();
}
public class ConcurrentLinkedDeque<E> extends java.util.AbstractCollection<E> implements java.util.Deque<E> java.io.Serializable {
diff --git a/api/removed.txt b/api/removed.txt
index 74a9346..a395cc7 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -444,13 +444,12 @@
method @Deprecated @NonNull public static android.net.Uri createPending(@NonNull android.content.Context, @NonNull android.provider.MediaStore.PendingParams);
method @Deprecated @NonNull public static java.util.Set<java.lang.String> getAllVolumeNames(@NonNull android.content.Context);
method @Deprecated @NonNull public static android.provider.MediaStore.PendingSession openPending(@NonNull android.content.Context, @NonNull android.net.Uri);
- method @Deprecated @NonNull public static android.net.Uri setIncludeTrashed(@NonNull android.net.Uri);
- method @Deprecated public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri);
- method @Deprecated public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri, long);
- method @Deprecated public static void untrash(@NonNull android.content.Context, @NonNull android.net.Uri);
}
public static interface MediaStore.Audio.AudioColumns extends android.provider.MediaStore.MediaColumns {
+ field public static final String ALBUM = "album";
+ field public static final String ARTIST = "artist";
+ field public static final String COMPOSER = "composer";
field public static final String DURATION = "duration";
}
@@ -458,6 +457,10 @@
field @Deprecated public static final String DESCRIPTION = "description";
}
+ public static interface MediaStore.Files.FileColumns extends android.provider.MediaStore.MediaColumns {
+ field public static final String TITLE = "title";
+ }
+
public static interface MediaStore.Images.ImageColumns extends android.provider.MediaStore.MediaColumns {
field public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
field public static final String BUCKET_ID = "bucket_id";
@@ -468,10 +471,6 @@
public static interface MediaStore.MediaColumns extends android.provider.BaseColumns {
field @Deprecated public static final String GROUP_ID = "group_id";
- field @Deprecated public static final String HASH = "_hash";
- field @Deprecated public static final String IS_TRASHED = "is_trashed";
- field @Deprecated public static final String PRIMARY_DIRECTORY = "primary_directory";
- field @Deprecated public static final String SECONDARY_DIRECTORY = "secondary_directory";
}
@Deprecated public static class MediaStore.PendingParams {
@@ -491,11 +490,14 @@
}
public static interface MediaStore.Video.VideoColumns extends android.provider.MediaStore.MediaColumns {
+ field public static final String ALBUM = "album";
+ field public static final String ARTIST = "artist";
field public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
field public static final String BUCKET_ID = "bucket_id";
field public static final String DATE_TAKEN = "datetaken";
field public static final String DURATION = "duration";
field public static final String GROUP_ID = "group_id";
+ field public static final String RESOLUTION = "resolution";
}
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
diff --git a/api/system-current.txt b/api/system-current.txt
index e525a71..e963560 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -75,6 +75,7 @@
field public static final String GET_TOP_ACTIVITY_INFO = "android.permission.GET_TOP_ACTIVITY_INFO";
field public static final String GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS = "android.permission.GRANT_PROFILE_OWNER_DEVICE_IDS_ACCESS";
field public static final String GRANT_RUNTIME_PERMISSIONS = "android.permission.GRANT_RUNTIME_PERMISSIONS";
+ field public static final String GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS = "android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS";
field public static final String HARDWARE_TEST = "android.permission.HARDWARE_TEST";
field public static final String HDMI_CEC = "android.permission.HDMI_CEC";
field public static final String HIDE_NON_SYSTEM_OVERLAY_WINDOWS = "android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS";
@@ -391,7 +392,7 @@
field public static final int UID_STATE_CACHED = 700; // 0x2bc
field public static final int UID_STATE_FOREGROUND = 500; // 0x1f4
field public static final int UID_STATE_FOREGROUND_SERVICE = 400; // 0x190
- field public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300; // 0x12c
+ field @Deprecated public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300; // 0x12c
field public static final int UID_STATE_PERSISTENT = 100; // 0x64
field public static final int UID_STATE_TOP = 200; // 0xc8
}
@@ -602,7 +603,7 @@
method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public byte[] getStatsMetadata() throws android.app.StatsManager.StatsUnavailableException;
method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void removeConfig(long) throws android.app.StatsManager.StatsUnavailableException;
method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean removeConfiguration(long);
- method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @NonNull public long[] setActiveConfigsChangedOperation(@Nullable android.app.PendingIntent) throws android.app.StatsManager.StatsUnavailableException;
+ method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public long[] setActiveConfigsChangedOperation(@Nullable android.app.PendingIntent) throws android.app.StatsManager.StatsUnavailableException;
method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void setBroadcastSubscriber(android.app.PendingIntent, long, long) throws android.app.StatsManager.StatsUnavailableException;
method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setBroadcastSubscriber(long, long, android.app.PendingIntent);
method @Deprecated @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public boolean setDataFetchOperation(long, android.app.PendingIntent);
@@ -1399,7 +1400,7 @@
method public abstract void sendBroadcast(android.content.Intent, @Nullable String, @Nullable android.os.Bundle);
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public abstract void sendBroadcastAsUser(@RequiresPermission android.content.Intent, android.os.UserHandle, @Nullable String, @Nullable android.os.Bundle);
method public abstract void sendOrderedBroadcast(@NonNull android.content.Intent, @Nullable String, @Nullable android.os.Bundle, @Nullable android.content.BroadcastReceiver, @Nullable android.os.Handler, int, @Nullable String, @Nullable android.os.Bundle);
- method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public void startActivityAsUser(@RequiresPermission @NonNull android.content.Intent, @NonNull android.os.UserHandle);
+ method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public void startActivityAsUser(@NonNull @RequiresPermission android.content.Intent, @NonNull android.os.UserHandle);
field public static final String APP_PREDICTION_SERVICE = "app_prediction";
field public static final String BACKUP_SERVICE = "backup";
field public static final String BATTERY_STATS_SERVICE = "batterystats";
@@ -1892,8 +1893,8 @@
public final class RollbackManager {
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender);
- method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
- method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks();
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, "android.permission.TEST_MANAGE_ROLLBACKS"}) public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks();
field public static final String EXTRA_STATUS = "android.content.rollback.extra.STATUS";
field public static final String EXTRA_STATUS_MESSAGE = "android.content.rollback.extra.STATUS_MESSAGE";
field public static final int STATUS_FAILURE = 1; // 0x1
@@ -2404,24 +2405,24 @@
}
public final class ContextHubManager {
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback, @NonNull java.util.concurrent.Executor);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.app.PendingIntent, long);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubTransaction<java.lang.Void> disableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubTransaction<java.lang.Void> enableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback, @NonNull java.util.concurrent.Executor);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.ContextHubClientCallback);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubClient createClient(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.app.PendingIntent, long);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> disableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> enableNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int[] findNanoAppOnHub(int, @NonNull android.hardware.location.NanoAppFilter);
method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int[] getContextHubHandles();
method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubInfo getContextHubInfo(int);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public java.util.List<android.hardware.location.ContextHubInfo> getContextHubs();
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<android.hardware.location.ContextHubInfo> getContextHubs();
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.NanoAppInstanceInfo getNanoAppInstanceInfo(int);
method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int loadNanoApp(int, @NonNull android.hardware.location.NanoApp);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubTransaction<java.lang.Void> loadNanoApp(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.NanoAppBinary);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubTransaction<java.util.List<android.hardware.location.NanoAppState>> queryNanoApps(@NonNull android.hardware.location.ContextHubInfo);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> loadNanoApp(@NonNull android.hardware.location.ContextHubInfo, @NonNull android.hardware.location.NanoAppBinary);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.util.List<android.hardware.location.NanoAppState>> queryNanoApps(@NonNull android.hardware.location.ContextHubInfo);
method @Deprecated public int registerCallback(@NonNull android.hardware.location.ContextHubManager.Callback);
method @Deprecated public int registerCallback(android.hardware.location.ContextHubManager.Callback, android.os.Handler);
method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int sendMessage(int, int, @NonNull android.hardware.location.ContextHubMessage);
method @Deprecated @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int unloadNanoApp(int);
- method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) @NonNull public android.hardware.location.ContextHubTransaction<java.lang.Void> unloadNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.hardware.location.ContextHubTransaction<java.lang.Void> unloadNanoApp(@NonNull android.hardware.location.ContextHubInfo, long);
method @Deprecated public int unregisterCallback(@NonNull android.hardware.location.ContextHubManager.Callback);
field public static final int EVENT_HUB_RESET = 6; // 0x6
field public static final int EVENT_NANOAPP_ABORTED = 4; // 0x4
@@ -3107,7 +3108,7 @@
}
public final class UsbPort {
- method @RequiresPermission(android.Manifest.permission.MANAGE_USB) @Nullable public android.hardware.usb.UsbPortStatus getStatus();
+ method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USB) public android.hardware.usb.UsbPortStatus getStatus();
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setRoles(int, int);
}
@@ -3488,7 +3489,8 @@
method @NonNull public static android.location.LocationRequest createFromDeprecatedCriteria(@NonNull android.location.Criteria, long, float, boolean);
method @NonNull public static android.location.LocationRequest createFromDeprecatedProvider(@NonNull String, long, float, boolean);
method public int describeContents();
- method public long getExpireAt();
+ method @Deprecated public long getExpireAt();
+ method public long getExpireIn();
method public long getFastestInterval();
method public boolean getHideFromAppOps();
method public long getInterval();
@@ -3499,12 +3501,12 @@
method @Nullable public android.os.WorkSource getWorkSource();
method public boolean isLocationSettingsIgnored();
method public boolean isLowPowerMode();
- method @NonNull public android.location.LocationRequest setExpireAt(long);
+ method @Deprecated @NonNull public android.location.LocationRequest setExpireAt(long);
method @NonNull public android.location.LocationRequest setExpireIn(long);
method @NonNull public android.location.LocationRequest setFastestInterval(long);
method public void setHideFromAppOps(boolean);
method @NonNull public android.location.LocationRequest setInterval(long);
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @NonNull public android.location.LocationRequest setLocationSettingsIgnored(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest setLocationSettingsIgnored(boolean);
method @NonNull public android.location.LocationRequest setLowPowerMode(boolean);
method @NonNull public android.location.LocationRequest setNumUpdates(int);
method @NonNull public android.location.LocationRequest setProvider(@NonNull String);
@@ -3835,7 +3837,7 @@
method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public void deleteModel(java.util.UUID);
method public int getDetectionServiceOperationsTimeout();
method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.media.soundtrigger.SoundTriggerManager.Model getModel(java.util.UUID);
- method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) @Nullable public android.hardware.soundtrigger.SoundTrigger.ModuleProperties getModuleProperties();
+ method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.hardware.soundtrigger.SoundTrigger.ModuleProperties getModuleProperties();
method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public void updateModel(android.media.soundtrigger.SoundTriggerManager.Model);
}
@@ -4523,7 +4525,8 @@
method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException;
method @NonNull public static java.net.SocketAddress makeNetlinkSocketAddress(int, int);
method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int);
- method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]);
+ method @Deprecated @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]);
+ method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int, @NonNull byte[]);
}
}
@@ -4742,6 +4745,39 @@
field @Deprecated public byte id;
}
+ public final class SoftApConfiguration implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public android.net.MacAddress getBssid();
+ method @Nullable public String getSsid();
+ method @Nullable public String getWpa2Passphrase();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApConfiguration> CREATOR;
+ }
+
+ public static final class SoftApConfiguration.Builder {
+ ctor public SoftApConfiguration.Builder();
+ ctor public SoftApConfiguration.Builder(@NonNull android.net.wifi.SoftApConfiguration);
+ method @NonNull public android.net.wifi.SoftApConfiguration build();
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setBssid(@Nullable android.net.MacAddress);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setSsid(@Nullable String);
+ method @NonNull public android.net.wifi.SoftApConfiguration.Builder setWpa2Passphrase(@Nullable String);
+ }
+
+ public final class SoftApInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getBandwidth();
+ method public int getFrequency();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CHANNEL_WIDTH_160MHZ = 6; // 0x6
+ field public static final int CHANNEL_WIDTH_20MHZ = 2; // 0x2
+ field public static final int CHANNEL_WIDTH_20MHZ_NOHT = 1; // 0x1
+ field public static final int CHANNEL_WIDTH_40MHZ = 3; // 0x3
+ field public static final int CHANNEL_WIDTH_80MHZ = 4; // 0x4
+ field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 5; // 0x5
+ field public static final int CHANNEL_WIDTH_INVALID = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApInfo> CREATOR;
+ }
+
public final class WifiClient implements android.os.Parcelable {
method public int describeContents();
method @NonNull public android.net.MacAddress getMacAddress();
@@ -4754,6 +4790,7 @@
method @Deprecated public boolean isEphemeral();
method @Deprecated public boolean isNoInternetAccessExpected();
field @Deprecated public boolean allowAutojoin;
+ field @Deprecated public int carrierId;
field @Deprecated public String creatorName;
field @Deprecated public int creatorUid;
field @Deprecated public String lastUpdateName;
@@ -4797,6 +4834,7 @@
method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public boolean setWifiApConfiguration(android.net.wifi.WifiConfiguration);
method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsConfiguratorInitiator(@NonNull String, int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startEasyConnectAsEnrolleeInitiator(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.EasyConnectStatusCallback);
+ method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startLocalOnlyHotspot(@NonNull android.net.wifi.SoftApConfiguration, @Nullable java.util.concurrent.Executor, @Nullable android.net.wifi.WifiManager.LocalOnlyHotspotCallback);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public boolean startScan(android.os.WorkSource);
method @RequiresPermission(anyOf={"android.permission.NETWORK_STACK", android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public boolean startSoftAp(@Nullable android.net.wifi.WifiConfiguration);
method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD}) public void startSubscriptionProvisioning(@NonNull android.net.wifi.hotspot2.OsuProvider, @NonNull java.util.concurrent.Executor, @NonNull android.net.wifi.hotspot2.ProvisioningCallback);
@@ -4860,10 +4898,14 @@
field public int numUsage;
}
+ public static final class WifiNetworkSuggestion.Builder {
+ method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) public android.net.wifi.WifiNetworkSuggestion.Builder setCarrierId(int);
+ }
+
public class WifiScanner {
method @Deprecated public void configureWifiChange(int, int, int, int, int, android.net.wifi.WifiScanner.BssidInfo[]);
method @Deprecated public void configureWifiChange(android.net.wifi.WifiScanner.WifiChangeSettings);
- method @Nullable @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<java.lang.Integer> getAvailableChannels(int);
+ method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public java.util.List<java.lang.Integer> getAvailableChannels(int);
method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public boolean getScanResults();
method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startBackgroundScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener);
method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void startBackgroundScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener, android.os.WorkSource);
@@ -5222,7 +5264,8 @@
}
public class BatteryStatsManager {
- method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) @NonNull public android.os.connectivity.WifiBatteryStats getWifiBatteryStats();
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.CellularBatteryStats getCellularBatteryStats();
+ method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.os.connectivity.WifiBatteryStats getWifiBatteryStats();
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteFullWifiLockAcquiredFromSource(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteFullWifiLockReleasedFromSource(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void noteWifiBatchedScanStartedFromSource(@NonNull android.os.WorkSource, @IntRange(from=0) int);
@@ -5442,8 +5485,8 @@
method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void cancelAuthorization(android.os.IncidentManager.AuthListener);
method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void deleteIncidentReports(android.net.Uri);
method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public void denyReport(android.net.Uri);
- method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @Nullable public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri);
- method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @NonNull public java.util.List<android.net.Uri> getIncidentReportList(String);
+ method @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri);
+ method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public java.util.List<android.net.Uri> getIncidentReportList(String);
method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public java.util.List<android.os.IncidentManager.PendingReport> getPendingReports();
method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void reportIncident(android.os.IncidentReportArgs);
method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener);
@@ -5674,6 +5717,7 @@
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<android.os.UserManager.EnforcingUser> getUserRestrictionSources(String, android.os.UserHandle);
method @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public int getUserSwitchability();
method public boolean hasRestrictedProfiles();
+ method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public boolean hasUserRestrictionForUser(@NonNull String, @NonNull android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isAdminUser();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isGuestUser();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isManagedProfile();
@@ -5728,6 +5772,26 @@
package android.os.connectivity {
+ public final class CellularBatteryStats implements android.os.Parcelable {
+ method public int describeContents();
+ method public long getEnergyConsumedMaMillis();
+ method public long getIdleTimeMillis();
+ method public long getKernelActiveTimeMillis();
+ method public long getLoggingDurationMillis();
+ method public long getMonitoredRailChargeConsumedMaMillis();
+ method public long getNumBytesRx();
+ method public long getNumBytesTx();
+ method public long getNumPacketsRx();
+ method public long getNumPacketsTx();
+ method public long getRxTimeMillis();
+ method public long getSleepTimeMillis();
+ method @NonNull public long[] getTimeInRatMicros();
+ method @NonNull public long[] getTimeInRxSignalStrengthLevelMicros();
+ method @NonNull public long[] getTxTimeMillis();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.os.connectivity.CellularBatteryStats> CREATOR;
+ }
+
public final class WifiBatteryStats implements android.os.Parcelable {
method public int describeContents();
method public long getEnergyConsumedMaMillis();
@@ -5993,7 +6057,7 @@
field public static final String NAMESPACE_AUTOFILL = "autofill";
field public static final String NAMESPACE_CONNECTIVITY = "connectivity";
field public static final String NAMESPACE_CONTENT_CAPTURE = "content_capture";
- field public static final String NAMESPACE_DEX_BOOT = "dex_boot";
+ field @Deprecated public static final String NAMESPACE_DEX_BOOT = "dex_boot";
field public static final String NAMESPACE_DISPLAY_MANAGER = "display_manager";
field public static final String NAMESPACE_GAME_DRIVER = "game_driver";
field public static final String NAMESPACE_INPUT_NATIVE_BOOT = "input_native_boot";
@@ -6254,15 +6318,21 @@
field public static final String DELIVERY_TIME = "date";
field public static final String ETWS_WARNING_TYPE = "etws_warning_type";
field public static final String GEOGRAPHICAL_SCOPE = "geo_scope";
+ field public static final String GEOMETRIES = "geometries";
field public static final String LAC = "lac";
field public static final String LANGUAGE_CODE = "language";
+ field public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time";
field public static final String MESSAGE_BODY = "body";
+ field public static final String MESSAGE_BROADCASTED = "message_broadcasted";
field public static final String MESSAGE_FORMAT = "format";
+ field @NonNull @RequiresPermission(android.Manifest.permission.READ_CELL_BROADCASTS) public static final android.net.Uri MESSAGE_HISTORY_URI;
field public static final String MESSAGE_PRIORITY = "priority";
field public static final String MESSAGE_READ = "read";
field public static final String PLMN = "plmn";
+ field public static final String RECEIVED_TIME = "received_time";
field public static final String SERIAL_NUMBER = "serial_number";
field public static final String SERVICE_CATEGORY = "service_category";
+ field public static final String SLOT_INDEX = "slot_index";
}
public final class TimeZoneRulesDataContract {
@@ -6286,7 +6356,7 @@
package android.security.keystore {
public abstract class AttestationUtils {
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @NonNull public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException;
field public static final int ID_TYPE_IMEI = 2; // 0x2
field public static final int ID_TYPE_MEID = 3; // 0x3
field public static final int ID_TYPE_SERIAL = 1; // 0x1
@@ -6367,18 +6437,18 @@
}
public class RecoveryController {
- method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public android.security.keystore.recovery.RecoverySession createRecoverySession();
+ method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public android.security.keystore.recovery.RecoverySession createRecoverySession();
method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.security.Key generateKey(@NonNull String) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException;
- method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public java.security.Key generateKey(@NonNull String, @Nullable byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException;
- method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public java.util.List<java.lang.String> getAliases() throws android.security.keystore.recovery.InternalRecoveryServiceException;
- method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public static android.security.keystore.recovery.RecoveryController getInstance(@NonNull android.content.Context);
- method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @Nullable public java.security.Key getKey(@NonNull String) throws android.security.keystore.recovery.InternalRecoveryServiceException, java.security.UnrecoverableKeyException;
- method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @Nullable public android.security.keystore.recovery.KeyChainSnapshot getKeyChainSnapshot() throws android.security.keystore.recovery.InternalRecoveryServiceException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.security.Key generateKey(@NonNull String, @Nullable byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.util.List<java.lang.String> getAliases() throws android.security.keystore.recovery.InternalRecoveryServiceException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public static android.security.keystore.recovery.RecoveryController getInstance(@NonNull android.content.Context);
+ method @Nullable @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.security.Key getKey(@NonNull String) throws android.security.keystore.recovery.InternalRecoveryServiceException, java.security.UnrecoverableKeyException;
+ method @Nullable @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public android.security.keystore.recovery.KeyChainSnapshot getKeyChainSnapshot() throws android.security.keystore.recovery.InternalRecoveryServiceException;
method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public int[] getRecoverySecretTypes() throws android.security.keystore.recovery.InternalRecoveryServiceException;
method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public int getRecoveryStatus(@NonNull String) throws android.security.keystore.recovery.InternalRecoveryServiceException;
- method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public java.util.Map<java.lang.String,java.security.cert.X509Certificate> getRootCertificates();
+ method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.util.Map<java.lang.String,java.security.cert.X509Certificate> getRootCertificates();
method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.security.Key importKey(@NonNull String, @NonNull byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException;
- method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public java.security.Key importKey(@NonNull String, @NonNull byte[], @Nullable byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.security.Key importKey(@NonNull String, @NonNull byte[], @Nullable byte[]) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.LockScreenRequiredException;
method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public void initRecoveryService(@NonNull String, @NonNull byte[], @NonNull byte[]) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public static boolean isRecoverableKeyStoreEnabled(@NonNull android.content.Context);
method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public void removeKey(@NonNull String) throws android.security.keystore.recovery.InternalRecoveryServiceException;
@@ -6393,8 +6463,8 @@
public class RecoverySession implements java.lang.AutoCloseable {
method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public void close();
- method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public java.util.Map<java.lang.String,java.security.Key> recoverKeyChainSnapshot(@NonNull byte[], @NonNull java.util.List<android.security.keystore.recovery.WrappedApplicationKey>) throws android.security.keystore.recovery.DecryptionFailedException, android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.SessionExpiredException;
- method @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) @NonNull public byte[] start(@NonNull String, @NonNull java.security.cert.CertPath, @NonNull byte[], @NonNull byte[], @NonNull java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public java.util.Map<java.lang.String,java.security.Key> recoverKeyChainSnapshot(@NonNull byte[], @NonNull java.util.List<android.security.keystore.recovery.WrappedApplicationKey>) throws android.security.keystore.recovery.DecryptionFailedException, android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.SessionExpiredException;
+ method @NonNull @RequiresPermission(android.Manifest.permission.RECOVER_KEYSTORE) public byte[] start(@NonNull String, @NonNull java.security.cert.CertPath, @NonNull byte[], @NonNull byte[], @NonNull java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
}
public class SessionExpiredException extends java.security.GeneralSecurityException {
@@ -6537,7 +6607,29 @@
public abstract class ApnService extends android.app.Service {
ctor public ApnService();
method @NonNull public android.os.IBinder onBind(@Nullable android.content.Intent);
- method @WorkerThread @NonNull public abstract java.util.List<android.content.ContentValues> onRestoreApns(int);
+ method @NonNull @WorkerThread public abstract java.util.List<android.content.ContentValues> onRestoreApns(int);
+ }
+
+ public abstract class CarrierMessagingServiceWrapper {
+ ctor public CarrierMessagingServiceWrapper();
+ method public boolean bindToCarrierMessagingService(@NonNull android.content.Context, @NonNull String);
+ method public void disposeConnection(@NonNull android.content.Context);
+ method public void downloadMms(@NonNull android.net.Uri, int, @NonNull android.net.Uri, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper);
+ method public void filterSms(@NonNull android.service.carrier.MessagePdu, @NonNull String, int, int, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper);
+ method public abstract void onServiceReady();
+ method public void sendDataSms(@NonNull byte[], int, @NonNull String, int, int, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper);
+ method public void sendMms(@NonNull android.net.Uri, int, @NonNull android.net.Uri, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper);
+ method public void sendMultipartTextSms(@NonNull java.util.List<java.lang.String>, int, @NonNull String, int, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper);
+ method public void sendTextSms(@NonNull String, int, @NonNull String, int, @NonNull android.service.carrier.CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper);
+ }
+
+ public abstract static class CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper {
+ ctor public CarrierMessagingServiceWrapper.CarrierMessagingCallbackWrapper();
+ method public void onDownloadMmsComplete(int);
+ method public void onFilterComplete(int);
+ method public void onSendMmsComplete(int, @Nullable byte[]);
+ method public void onSendMultipartSmsComplete(int, @Nullable int[]);
+ method public void onSendSmsComplete(int, int);
}
}
@@ -6649,13 +6741,13 @@
method public android.service.euicc.EuiccProfileInfo.Builder setUiccAccessRule(@Nullable java.util.List<android.telephony.UiccAccessRule>);
}
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(flag=true, prefix={"POLICY_RULE_"}, value={android.service.euicc.EuiccProfileInfo.POLICY_RULE_DO_NOT_DISABLE, android.service.euicc.EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE, android.service.euicc.EuiccProfileInfo.POLICY_RULE_DELETE_AFTER_DISABLING}) public static @interface EuiccProfileInfo.PolicyRule {
+ @IntDef(flag=true, prefix={"POLICY_RULE_"}, value={android.service.euicc.EuiccProfileInfo.POLICY_RULE_DO_NOT_DISABLE, android.service.euicc.EuiccProfileInfo.POLICY_RULE_DO_NOT_DELETE, android.service.euicc.EuiccProfileInfo.POLICY_RULE_DELETE_AFTER_DISABLING}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccProfileInfo.PolicyRule {
}
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(prefix={"PROFILE_CLASS_"}, value={android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_TESTING, android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_PROVISIONING, android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL, 0xffffffff}) public static @interface EuiccProfileInfo.ProfileClass {
+ @IntDef(prefix={"PROFILE_CLASS_"}, value={android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_TESTING, android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_PROVISIONING, android.service.euicc.EuiccProfileInfo.PROFILE_CLASS_OPERATIONAL, 0xffffffff}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccProfileInfo.ProfileClass {
}
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(prefix={"PROFILE_STATE_"}, value={android.service.euicc.EuiccProfileInfo.PROFILE_STATE_DISABLED, android.service.euicc.EuiccProfileInfo.PROFILE_STATE_ENABLED, 0xffffffff}) public static @interface EuiccProfileInfo.ProfileState {
+ @IntDef(prefix={"PROFILE_STATE_"}, value={android.service.euicc.EuiccProfileInfo.PROFILE_STATE_DISABLED, android.service.euicc.EuiccProfileInfo.PROFILE_STATE_ENABLED, 0xffffffff}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccProfileInfo.ProfileState {
}
public abstract class EuiccService extends android.app.Service {
@@ -6834,7 +6926,7 @@
package android.service.oemlock {
public class OemLockManager {
- method @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE) @Nullable public String getLockName();
+ method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE) public String getLockName();
method @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE) public boolean isOemUnlockAllowedByCarrier();
method @RequiresPermission(android.Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE) public boolean isOemUnlockAllowedByUser();
method @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE) public void setOemUnlockAllowedByCarrier(boolean, @Nullable byte[]);
@@ -6847,7 +6939,7 @@
public class PersistentDataBlockManager {
method @RequiresPermission("android.permission.ACCESS_PDB_STATE") public int getDataBlockSize();
- method @RequiresPermission(anyOf={android.Manifest.permission.READ_OEM_UNLOCK_STATE, "android.permission.OEM_UNLOCK_STATE"}) @android.service.persistentdata.PersistentDataBlockManager.FlashLockState public int getFlashLockState();
+ method @android.service.persistentdata.PersistentDataBlockManager.FlashLockState @RequiresPermission(anyOf={android.Manifest.permission.READ_OEM_UNLOCK_STATE, "android.permission.OEM_UNLOCK_STATE"}) public int getFlashLockState();
method public long getMaximumDataBlockSize();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_OEM_UNLOCK_STATE, "android.permission.OEM_UNLOCK_STATE"}) public boolean getOemUnlockEnabled();
method public byte[] read();
@@ -7435,11 +7527,27 @@
method @NonNull public android.telephony.CarrierRestrictionRules.Builder setMultiSimPolicy(int);
}
+ public class CbGeoUtils {
+ }
+
+ public static interface CbGeoUtils.Geometry {
+ method public boolean contains(@NonNull android.telephony.CbGeoUtils.LatLng);
+ }
+
+ public static class CbGeoUtils.LatLng {
+ ctor public CbGeoUtils.LatLng(double, double);
+ method public double distance(@NonNull android.telephony.CbGeoUtils.LatLng);
+ method @NonNull public android.telephony.CbGeoUtils.LatLng subtract(@NonNull android.telephony.CbGeoUtils.LatLng);
+ field public final double lat;
+ field public final double lng;
+ }
+
public abstract class CellBroadcastService extends android.app.Service {
ctor public CellBroadcastService();
- method @CallSuper public android.os.IBinder onBind(android.content.Intent);
- method public abstract void onCdmaCellBroadcastSms(int, byte[], int);
- method public abstract void onGsmCellBroadcastSms(int, byte[]);
+ method @CallSuper public android.os.IBinder onBind(@Nullable android.content.Intent);
+ method public abstract void onCdmaCellBroadcastSms(int, @NonNull byte[], int);
+ method public abstract void onCdmaScpMessage(int, @NonNull java.util.List<android.telephony.cdma.CdmaSmsCbProgramData>, @NonNull String, @NonNull java.util.function.Consumer<android.os.Bundle>);
+ method public abstract void onGsmCellBroadcastSms(int, @NonNull byte[]);
field public static final String CELL_BROADCAST_SERVICE_INTERFACE = "android.telephony.CellBroadcastService";
}
@@ -7870,6 +7978,14 @@
field public static final int WIFI_LOST = 59; // 0x3b
}
+ public final class ImsiEncryptionInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public String getKeyIdentifier();
+ method @Nullable public java.security.PublicKey getPublicKey();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ImsiEncryptionInfo> CREATOR;
+ }
+
public final class LteVopsSupportInfo implements android.os.Parcelable {
ctor public LteVopsSupportInfo(int, int);
method public int describeContents();
@@ -8253,6 +8369,7 @@
method public int getGeographicalScope();
method @Nullable public String getLanguageCode();
method @NonNull public android.telephony.SmsCbLocation getLocation();
+ method public int getMaximumWaitingDuration();
method @Nullable public String getMessageBody();
method public int getMessageFormat();
method public int getMessagePriority();
@@ -8353,6 +8470,7 @@
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enableVideoCalling(boolean);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int);
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
@@ -8406,7 +8524,9 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean rebootRadio();
method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_FINE_LOCATION, android.Manifest.permission.MODIFY_PHONE_STATE}) public void requestCellInfoUpdate(@NonNull android.os.WorkSource, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig();
+ method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules);
@@ -8429,6 +8549,7 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
method public void updateServiceLocation();
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
+ field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED = "android.telephony.action.OTA_EMERGENCY_NUMBER_DB_INSTALLED";
field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
@@ -8441,6 +8562,8 @@
field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
+ field public static final int KEY_TYPE_EPDG = 1; // 0x1
+ field public static final int KEY_TYPE_WLAN = 2; // 0x2
field public static final long NETWORK_TYPE_BITMASK_1xRTT = 64L; // 0x40L
field public static final long NETWORK_TYPE_BITMASK_CDMA = 8L; // 0x8L
field public static final long NETWORK_TYPE_BITMASK_EDGE = 2L; // 0x2L
@@ -8732,10 +8855,10 @@
field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff
}
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(prefix={"CANCEL_REASON_"}, value={android.telephony.euicc.EuiccCardManager.CANCEL_REASON_END_USER_REJECTED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_POSTPONED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_TIMEOUT, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_PPR_NOT_ALLOWED}) public static @interface EuiccCardManager.CancelReason {
+ @IntDef(prefix={"CANCEL_REASON_"}, value={android.telephony.euicc.EuiccCardManager.CANCEL_REASON_END_USER_REJECTED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_POSTPONED, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_TIMEOUT, android.telephony.euicc.EuiccCardManager.CANCEL_REASON_PPR_NOT_ALLOWED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccCardManager.CancelReason {
}
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(flag=true, prefix={"RESET_OPTION_"}, value={android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS}) public static @interface EuiccCardManager.ResetOption {
+ @IntDef(flag=true, prefix={"RESET_OPTION_"}, value={android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES, android.telephony.euicc.EuiccCardManager.RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccCardManager.ResetOption {
}
public static interface EuiccCardManager.ResultCallback<T> {
@@ -8791,7 +8914,7 @@
field public static final int EVENT_INSTALL = 1; // 0x1
}
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(flag=true, prefix={"EVENT_"}, value={android.telephony.euicc.EuiccNotification.EVENT_INSTALL, android.telephony.euicc.EuiccNotification.EVENT_ENABLE, android.telephony.euicc.EuiccNotification.EVENT_DISABLE, android.telephony.euicc.EuiccNotification.EVENT_DELETE}) public static @interface EuiccNotification.Event {
+ @IntDef(flag=true, prefix={"EVENT_"}, value={android.telephony.euicc.EuiccNotification.EVENT_INSTALL, android.telephony.euicc.EuiccNotification.EVENT_ENABLE, android.telephony.euicc.EuiccNotification.EVENT_DISABLE, android.telephony.euicc.EuiccNotification.EVENT_DELETE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccNotification.Event {
}
public final class EuiccRulesAuthTable implements android.os.Parcelable {
@@ -8809,7 +8932,7 @@
method public android.telephony.euicc.EuiccRulesAuthTable build();
}
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(flag=true, prefix={"POLICY_RULE_FLAG_"}, value={android.telephony.euicc.EuiccRulesAuthTable.POLICY_RULE_FLAG_CONSENT_REQUIRED}) public static @interface EuiccRulesAuthTable.PolicyRuleFlag {
+ @IntDef(flag=true, prefix={"POLICY_RULE_FLAG_"}, value={android.telephony.euicc.EuiccRulesAuthTable.POLICY_RULE_FLAG_CONSENT_REQUIRED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface EuiccRulesAuthTable.PolicyRuleFlag {
}
}
@@ -9018,17 +9141,23 @@
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR;
}
- public class ImsMmTelManager {
+ public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiModeSetting();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAdvancedCallingSettingEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isAvailable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isTtyOverVolteEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiRoamingSettingEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVoWiFiSettingEnabled();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isVtSettingEnabled();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
@@ -9038,7 +9167,8 @@
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean);
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterMmTelCapabilityCallback(@NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback);
field public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; // 0x1
field public static final int WIFI_MODE_WIFI_ONLY = 0; // 0x0
@@ -9050,12 +9180,8 @@
method public void onCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
}
- public static class ImsMmTelManager.RegistrationCallback {
- ctor public ImsMmTelManager.RegistrationCallback();
- method public void onRegistered(int);
- method public void onRegistering(int);
- method public void onTechnologyChangeFailed(int, @Nullable android.telephony.ims.ImsReasonInfo);
- method public void onUnregistered(@Nullable android.telephony.ims.ImsReasonInfo);
+ @Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback {
+ ctor @Deprecated public ImsMmTelManager.RegistrationCallback();
}
public final class ImsReasonInfo implements android.os.Parcelable {
@@ -9431,14 +9557,17 @@
}
public class ImsUtListener {
+ method public void onLineIdentificationSupplementaryServiceResponse(int, @NonNull android.telephony.ims.ImsSsInfo);
method public void onSupplementaryServiceIndication(android.telephony.ims.ImsSsData);
method public void onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]);
method public void onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]);
method public void onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]);
- method public void onUtConfigurationQueried(int, android.os.Bundle);
+ method @Deprecated public void onUtConfigurationQueried(int, android.os.Bundle);
method public void onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo);
method public void onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo);
method public void onUtConfigurationUpdated(int);
+ field @Deprecated public static final String BUNDLE_KEY_CLIR = "queryClir";
+ field @Deprecated public static final String BUNDLE_KEY_SSINFO = "imsSsInfo";
}
public abstract class ImsVideoCallProvider {
@@ -9465,12 +9594,12 @@
public class ProvisioningManager {
method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
- method @WorkerThread @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getProvisioningIntValue(int);
- method @WorkerThread @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean getProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public int getProvisioningIntValue(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public boolean getProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @WorkerThread public String getProvisioningStringValue(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
- method @WorkerThread @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b
@@ -9487,6 +9616,24 @@
method public void onProvisioningStringChanged(int, @NonNull String);
}
+ public interface RegistrationManager {
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
+ field public static final int REGISTRATION_STATE_NOT_REGISTERED = 0; // 0x0
+ field public static final int REGISTRATION_STATE_REGISTERED = 2; // 0x2
+ field public static final int REGISTRATION_STATE_REGISTERING = 1; // 0x1
+ }
+
+ public static class RegistrationManager.RegistrationCallback {
+ ctor public RegistrationManager.RegistrationCallback();
+ method public void onRegistered(int);
+ method public void onRegistering(int);
+ method public void onTechnologyChangeFailed(int, @Nullable android.telephony.ims.ImsReasonInfo);
+ method public void onUnregistered(@Nullable android.telephony.ims.ImsReasonInfo);
+ }
+
}
package android.telephony.ims.feature {
@@ -9551,6 +9698,8 @@
method public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
method public void setUiTtyMode(int, @Nullable android.os.Message);
method @android.telephony.ims.feature.MmTelFeature.ProcessCallResult public int shouldProcessCall(@NonNull String[]);
+ field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
+ field public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD";
field public static final int PROCESS_CALL_CSFB = 1; // 0x1
field public static final int PROCESS_CALL_IMS = 0; // 0x0
}
diff --git a/api/system-lint-baseline.txt b/api/system-lint-baseline.txt
index 57a853a..21526d0 100644
--- a/api/system-lint-baseline.txt
+++ b/api/system-lint-baseline.txt
@@ -135,6 +135,12 @@
+MutableBareField: android.net.wifi.WifiConfiguration#allowAutojoin:
+
+MutableBareField: android.net.wifi.WifiConfiguration#carrierId:
+
+
+
NoClone: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0:
@@ -257,6 +263,8 @@
SamShouldBeLast: android.net.ConnectivityManager#createSocketKeepalive(android.net.Network, android.net.IpSecManager.UdpEncapsulationSocket, java.net.InetAddress, java.net.InetAddress, java.util.concurrent.Executor, android.net.SocketKeepalive.Callback):
+SamShouldBeLast: android.net.wifi.WifiManager#startLocalOnlyHotspot(android.net.wifi.SoftApConfiguration, java.util.concurrent.Executor, android.net.wifi.WifiManager.LocalOnlyHotspotCallback):
+
SamShouldBeLast: android.net.wifi.rtt.WifiRttManager#startRanging(android.net.wifi.rtt.RangingRequest, java.util.concurrent.Executor, android.net.wifi.rtt.RangingResultCallback):
SamShouldBeLast: android.nfc.NfcAdapter#enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle):
diff --git a/api/test-current.txt b/api/test-current.txt
index 5247bd1..466320b 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -71,6 +71,9 @@
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener);
method public static void resumeAppSwitches() throws android.os.RemoteException;
method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int);
+ field public static final int PROCESS_CAPABILITY_ALL = 1; // 0x1
+ field public static final int PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1; // 0x1
+ field public static final int PROCESS_CAPABILITY_NONE = 0; // 0x0
}
public static interface ActivityManager.OnUidImportanceListener {
@@ -233,7 +236,7 @@
field public static final int UID_STATE_CACHED = 700; // 0x2bc
field public static final int UID_STATE_FOREGROUND = 500; // 0x1f4
field public static final int UID_STATE_FOREGROUND_SERVICE = 400; // 0x190
- field public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300; // 0x12c
+ field @Deprecated public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300; // 0x12c
field public static final int UID_STATE_PERSISTENT = 100; // 0x64
field public static final int UID_STATE_TOP = 200; // 0xc8
}
@@ -860,8 +863,8 @@
method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void blockRollbackManager(long);
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender);
method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String);
- method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
- method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks();
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public java.util.List<android.content.rollback.RollbackInfo> getRecentlyCommittedRollbacks();
method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void reloadPersistedData();
field public static final String EXTRA_STATUS = "android.content.rollback.extra.STATUS";
field public static final String EXTRA_STATUS_MESSAGE = "android.content.rollback.extra.STATUS_MESSAGE";
@@ -1144,17 +1147,20 @@
public final class LocationRequest implements android.os.Parcelable {
method @NonNull public static android.location.LocationRequest create();
method public int describeContents();
- method public long getExpireAt();
+ method @Deprecated public long getExpireAt();
+ method public long getExpireIn();
method public long getFastestInterval();
method public long getInterval();
method public int getNumUpdates();
method public int getQuality();
method public boolean isLocationSettingsIgnored();
- method @NonNull public android.location.LocationRequest setExpireAt(long);
+ method public boolean isLowPowerMode();
+ method @Deprecated @NonNull public android.location.LocationRequest setExpireAt(long);
method @NonNull public android.location.LocationRequest setExpireIn(long);
method @NonNull public android.location.LocationRequest setFastestInterval(long);
method @NonNull public android.location.LocationRequest setInterval(long);
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) @NonNull public android.location.LocationRequest setLocationSettingsIgnored(boolean);
+ method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest setLocationSettingsIgnored(boolean);
+ method @NonNull public android.location.LocationRequest setLowPowerMode(boolean);
method @NonNull public android.location.LocationRequest setNumUpdates(int);
method @NonNull public android.location.LocationRequest setProvider(@NonNull String);
method @NonNull public android.location.LocationRequest setQuality(int);
@@ -1730,7 +1736,8 @@
method public static void closeSocket(@Nullable java.io.FileDescriptor) throws java.io.IOException;
method @NonNull public static java.net.SocketAddress makeNetlinkSocketAddress(int, int);
method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int);
- method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]);
+ method @Deprecated @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, @NonNull byte[]);
+ method @NonNull public static java.net.SocketAddress makePacketSocketAddress(int, int, @NonNull byte[]);
}
}
@@ -1928,8 +1935,8 @@
method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void cancelAuthorization(android.os.IncidentManager.AuthListener);
method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void deleteIncidentReports(android.net.Uri);
method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public void denyReport(android.net.Uri);
- method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @Nullable public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri);
- method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) @NonNull public java.util.List<android.net.Uri> getIncidentReportList(String);
+ method @Nullable @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public android.os.IncidentManager.IncidentReport getIncidentReport(android.net.Uri);
+ method @NonNull @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public java.util.List<android.net.Uri> getIncidentReportList(String);
method @RequiresPermission(android.Manifest.permission.APPROVE_INCIDENT_REPORTS) public java.util.List<android.os.IncidentManager.PendingReport> getPendingReports();
method @RequiresPermission(allOf={android.Manifest.permission.DUMP, android.Manifest.permission.PACKAGE_USAGE_STATS}) public void reportIncident(android.os.IncidentReportArgs);
method @RequiresPermission("android.permission.REQUEST_INCIDENT_REPORT_APPROVAL") public void requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener);
@@ -2071,6 +2078,8 @@
method @NonNull public static String get(@NonNull String);
method @NonNull public static String get(@NonNull String, @Nullable String);
method public static boolean getBoolean(@NonNull String, boolean);
+ method public static int getInt(@NonNull String, int);
+ method public static long getLong(@NonNull String, long);
}
public final class UserHandle implements android.os.Parcelable {
@@ -2425,6 +2434,7 @@
}
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
+ field public static final String APP_OPS_CONSTANTS = "app_ops_constants";
field public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
field public static final String AUTOMATIC_POWER_SAVE_MODE = "automatic_power_save_mode";
field public static final String BATTERY_SAVER_CONSTANTS = "battery_saver_constants";
@@ -2464,6 +2474,36 @@
field public static final String VOICE_INTERACTION_SERVICE = "voice_interaction_service";
}
+ public static final class Telephony.CellBroadcasts implements android.provider.BaseColumns {
+ field public static final String CID = "cid";
+ field public static final String CMAS_CATEGORY = "cmas_category";
+ field public static final String CMAS_CERTAINTY = "cmas_certainty";
+ field public static final String CMAS_MESSAGE_CLASS = "cmas_message_class";
+ field public static final String CMAS_RESPONSE_TYPE = "cmas_response_type";
+ field public static final String CMAS_SEVERITY = "cmas_severity";
+ field public static final String CMAS_URGENCY = "cmas_urgency";
+ field @NonNull public static final android.net.Uri CONTENT_URI;
+ field public static final String DEFAULT_SORT_ORDER = "date DESC";
+ field public static final String DELIVERY_TIME = "date";
+ field public static final String ETWS_WARNING_TYPE = "etws_warning_type";
+ field public static final String GEOGRAPHICAL_SCOPE = "geo_scope";
+ field public static final String GEOMETRIES = "geometries";
+ field public static final String LAC = "lac";
+ field public static final String LANGUAGE_CODE = "language";
+ field public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time";
+ field public static final String MESSAGE_BODY = "body";
+ field public static final String MESSAGE_BROADCASTED = "message_broadcasted";
+ field public static final String MESSAGE_FORMAT = "format";
+ field @NonNull @RequiresPermission(android.Manifest.permission.READ_CELL_BROADCASTS) public static final android.net.Uri MESSAGE_HISTORY_URI;
+ field public static final String MESSAGE_PRIORITY = "priority";
+ field public static final String MESSAGE_READ = "read";
+ field public static final String PLMN = "plmn";
+ field public static final String RECEIVED_TIME = "received_time";
+ field public static final String SERIAL_NUMBER = "serial_number";
+ field public static final String SERVICE_CATEGORY = "service_category";
+ field public static final String SLOT_INDEX = "slot_index";
+ }
+
public static final class Telephony.Sms.Intents {
field public static final String SMS_CARRIER_PROVISION_ACTION = "android.provider.Telephony.SMS_CARRIER_PROVISION";
}
@@ -2486,7 +2526,7 @@
package android.security.keystore {
public abstract class AttestationUtils {
- method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @NonNull public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException;
+ method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public static java.security.cert.X509Certificate[] attestDeviceIds(android.content.Context, @NonNull int[], @NonNull byte[]) throws android.security.keystore.DeviceIdAttestationException;
field public static final int ID_TYPE_IMEI = 2; // 0x2
field public static final int ID_TYPE_MEID = 3; // 0x3
field public static final int ID_TYPE_SERIAL = 1; // 0x1
@@ -2870,10 +2910,35 @@
package android.telephony {
public final class AccessNetworkConstants {
+ field public static final int TRANSPORT_TYPE_INVALID = -1; // 0xffffffff
field public static final int TRANSPORT_TYPE_WLAN = 2; // 0x2
field public static final int TRANSPORT_TYPE_WWAN = 1; // 0x1
}
+ public final class CallQuality implements android.os.Parcelable {
+ ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int);
+ method public int describeContents();
+ method public int getAverageRelativeJitter();
+ method public int getAverageRoundTripTime();
+ method public int getCallDuration();
+ method public int getCodecType();
+ method public int getDownlinkCallQualityLevel();
+ method public int getMaxRelativeJitter();
+ method public int getNumRtpPacketsNotReceived();
+ method public int getNumRtpPacketsReceived();
+ method public int getNumRtpPacketsTransmitted();
+ method public int getNumRtpPacketsTransmittedLost();
+ method public int getUplinkCallQualityLevel();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CALL_QUALITY_BAD = 4; // 0x4
+ field public static final int CALL_QUALITY_EXCELLENT = 0; // 0x0
+ field public static final int CALL_QUALITY_FAIR = 2; // 0x2
+ field public static final int CALL_QUALITY_GOOD = 1; // 0x1
+ field public static final int CALL_QUALITY_NOT_AVAILABLE = 5; // 0x5
+ field public static final int CALL_QUALITY_POOR = 3; // 0x3
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallQuality> CREATOR;
+ }
+
public class CarrierConfigManager {
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void overrideConfig(int, @Nullable android.os.PersistableBundle);
}
@@ -2985,9 +3050,19 @@
field public static final int SMS_CATEGORY_STANDARD_SHORT_CODE = 2; // 0x2
}
+ public class SubscriptionManager {
+ field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
+ field @NonNull public static final android.net.Uri VT_ENABLED_CONTENT_URI;
+ field @NonNull public static final android.net.Uri WFC_ENABLED_CONTENT_URI;
+ field @NonNull public static final android.net.Uri WFC_MODE_CONTENT_URI;
+ field @NonNull public static final android.net.Uri WFC_ROAMING_ENABLED_CONTENT_URI;
+ field @NonNull public static final android.net.Uri WFC_ROAMING_MODE_CONTENT_URI;
+ }
+
public class TelephonyManager {
method public int checkCarrierPrivilegesForPackage(String);
method public int getCarrierIdListVersion();
+ method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
method @NonNull @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getNetworkCountryIso(int);
method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
@@ -3011,6 +3086,963 @@
}
+package android.telephony.ims {
+
+ public final class ImsCallForwardInfo implements android.os.Parcelable {
+ ctor public ImsCallForwardInfo(int, int, int, int, @NonNull String, int);
+ method public int describeContents();
+ method public int getCondition();
+ method public String getNumber();
+ method public int getServiceClass();
+ method public int getStatus();
+ method public int getTimeSeconds();
+ method public int getToA();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CDIV_CF_REASON_ALL = 4; // 0x4
+ field public static final int CDIV_CF_REASON_ALL_CONDITIONAL = 5; // 0x5
+ field public static final int CDIV_CF_REASON_BUSY = 1; // 0x1
+ field public static final int CDIV_CF_REASON_NOT_LOGGED_IN = 6; // 0x6
+ field public static final int CDIV_CF_REASON_NOT_REACHABLE = 3; // 0x3
+ field public static final int CDIV_CF_REASON_NO_REPLY = 2; // 0x2
+ field public static final int CDIV_CF_REASON_UNCONDITIONAL = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallForwardInfo> CREATOR;
+ field public static final int STATUS_ACTIVE = 1; // 0x1
+ field public static final int STATUS_NOT_ACTIVE = 0; // 0x0
+ field public static final int TYPE_OF_ADDRESS_INTERNATIONAL = 145; // 0x91
+ field public static final int TYPE_OF_ADDRESS_UNKNOWN = 129; // 0x81
+ }
+
+ public final class ImsCallProfile implements android.os.Parcelable {
+ ctor public ImsCallProfile();
+ ctor public ImsCallProfile(int, int);
+ ctor public ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile);
+ method public int describeContents();
+ method public String getCallExtra(String);
+ method public String getCallExtra(String, String);
+ method public boolean getCallExtraBoolean(String);
+ method public boolean getCallExtraBoolean(String, boolean);
+ method public int getCallExtraInt(String);
+ method public int getCallExtraInt(String, int);
+ method public android.os.Bundle getCallExtras();
+ method public int getCallType();
+ method public static int getCallTypeFromVideoState(int);
+ method public int getCallerNumberVerificationStatus();
+ method public int getEmergencyCallRouting();
+ method public int getEmergencyServiceCategories();
+ method @NonNull public java.util.List<java.lang.String> getEmergencyUrns();
+ method public android.telephony.ims.ImsStreamMediaProfile getMediaProfile();
+ method public int getRestrictCause();
+ method public int getServiceType();
+ method public static int getVideoStateFromCallType(int);
+ method public static int getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile);
+ method public boolean hasKnownUserIntentEmergency();
+ method public boolean isEmergencyCallTesting();
+ method public boolean isVideoCall();
+ method public boolean isVideoPaused();
+ method public static int presentationToOir(int);
+ method public void setCallExtra(String, String);
+ method public void setCallExtraBoolean(String, boolean);
+ method public void setCallExtraInt(String, int);
+ method public void setCallRestrictCause(int);
+ method public void setCallerNumberVerificationStatus(int);
+ method public void setEmergencyCallRouting(int);
+ method public void setEmergencyCallTesting(boolean);
+ method public void setEmergencyServiceCategories(int);
+ method public void setEmergencyUrns(@NonNull java.util.List<java.lang.String>);
+ method public void setHasKnownUserIntentEmergency(boolean);
+ method public void updateCallExtras(android.telephony.ims.ImsCallProfile);
+ method public void updateCallType(android.telephony.ims.ImsCallProfile);
+ method public void updateMediaProfile(android.telephony.ims.ImsCallProfile);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CALL_RESTRICT_CAUSE_DISABLED = 2; // 0x2
+ field public static final int CALL_RESTRICT_CAUSE_HD = 3; // 0x3
+ field public static final int CALL_RESTRICT_CAUSE_NONE = 0; // 0x0
+ field public static final int CALL_RESTRICT_CAUSE_RAT = 1; // 0x1
+ field public static final int CALL_TYPE_VIDEO_N_VOICE = 3; // 0x3
+ field public static final int CALL_TYPE_VOICE = 2; // 0x2
+ field public static final int CALL_TYPE_VOICE_N_VIDEO = 1; // 0x1
+ field public static final int CALL_TYPE_VS = 8; // 0x8
+ field public static final int CALL_TYPE_VS_RX = 10; // 0xa
+ field public static final int CALL_TYPE_VS_TX = 9; // 0x9
+ field public static final int CALL_TYPE_VT = 4; // 0x4
+ field public static final int CALL_TYPE_VT_NODIR = 7; // 0x7
+ field public static final int CALL_TYPE_VT_RX = 6; // 0x6
+ field public static final int CALL_TYPE_VT_TX = 5; // 0x5
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsCallProfile> CREATOR;
+ field public static final int DIALSTRING_NORMAL = 0; // 0x0
+ field public static final int DIALSTRING_SS_CONF = 1; // 0x1
+ field public static final int DIALSTRING_USSD = 2; // 0x2
+ field public static final String EXTRA_ADDITIONAL_CALL_INFO = "AdditionalCallInfo";
+ field public static final String EXTRA_ADDITIONAL_SIP_INVITE_FIELDS = "android.telephony.ims.extra.ADDITIONAL_SIP_INVITE_FIELDS";
+ field public static final String EXTRA_CALL_RAT_TYPE = "CallRadioTech";
+ field public static final String EXTRA_CHILD_NUMBER = "ChildNum";
+ field public static final String EXTRA_CNA = "cna";
+ field public static final String EXTRA_CNAP = "cnap";
+ field public static final String EXTRA_CODEC = "Codec";
+ field public static final String EXTRA_DIALSTRING = "dialstring";
+ field public static final String EXTRA_DISPLAY_TEXT = "DisplayText";
+ field public static final String EXTRA_EMERGENCY_CALL = "e_call";
+ field public static final String EXTRA_IS_CALL_PULL = "CallPull";
+ field public static final String EXTRA_OI = "oi";
+ field public static final String EXTRA_OIR = "oir";
+ field public static final String EXTRA_REMOTE_URI = "remote_uri";
+ field public static final String EXTRA_USSD = "ussd";
+ field public static final int OIR_DEFAULT = 0; // 0x0
+ field public static final int OIR_PRESENTATION_NOT_RESTRICTED = 2; // 0x2
+ field public static final int OIR_PRESENTATION_PAYPHONE = 4; // 0x4
+ field public static final int OIR_PRESENTATION_RESTRICTED = 1; // 0x1
+ field public static final int OIR_PRESENTATION_UNKNOWN = 3; // 0x3
+ field public static final int SERVICE_TYPE_EMERGENCY = 2; // 0x2
+ field public static final int SERVICE_TYPE_NONE = 0; // 0x0
+ field public static final int SERVICE_TYPE_NORMAL = 1; // 0x1
+ field public static final int VERIFICATION_STATUS_FAILED = 2; // 0x2
+ field public static final int VERIFICATION_STATUS_NOT_VERIFIED = 0; // 0x0
+ field public static final int VERIFICATION_STATUS_PASSED = 1; // 0x1
+ }
+
+ public class ImsCallSessionListener {
+ method public void callQualityChanged(@NonNull android.telephony.CallQuality);
+ method public void callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
+ method public void callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
+ method public void callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState);
+ method public void callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo);
+ method public void callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo);
+ method public void callSessionHeld(android.telephony.ims.ImsCallProfile);
+ method public void callSessionHoldFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionHoldReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionInitiated(android.telephony.ims.ImsCallProfile);
+ method public void callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionInviteParticipantsRequestDelivered();
+ method public void callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionMayHandover(int, int);
+ method public void callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase);
+ method public void callSessionMergeFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile);
+ method public void callSessionMultipartyStateChanged(boolean);
+ method public void callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile);
+ method public void callSessionRemoveParticipantsRequestDelivered();
+ method public void callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionResumeFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionResumeReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionResumed(android.telephony.ims.ImsCallProfile);
+ method public void callSessionRttAudioIndicatorChanged(@NonNull android.telephony.ims.ImsStreamMediaProfile);
+ method public void callSessionRttMessageReceived(String);
+ method public void callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionRttModifyResponseReceived(int);
+ method public void callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification);
+ method public void callSessionTerminated(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionTtyModeReceived(int);
+ method public void callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo);
+ method public void callSessionUpdateReceived(android.telephony.ims.ImsCallProfile);
+ method public void callSessionUpdated(android.telephony.ims.ImsCallProfile);
+ method public void callSessionUssdMessageReceived(int, String);
+ }
+
+ public final class ImsConferenceState implements android.os.Parcelable {
+ method public int describeContents();
+ method public static int getConnectionStateForStatus(String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsConferenceState> CREATOR;
+ field public static final String DISPLAY_TEXT = "display-text";
+ field public static final String ENDPOINT = "endpoint";
+ field public static final String SIP_STATUS_CODE = "sipstatuscode";
+ field public static final String STATUS = "status";
+ field public static final String STATUS_ALERTING = "alerting";
+ field public static final String STATUS_CONNECTED = "connected";
+ field public static final String STATUS_CONNECT_FAIL = "connect-fail";
+ field public static final String STATUS_DIALING_IN = "dialing-in";
+ field public static final String STATUS_DIALING_OUT = "dialing-out";
+ field public static final String STATUS_DISCONNECTED = "disconnected";
+ field public static final String STATUS_DISCONNECTING = "disconnecting";
+ field public static final String STATUS_MUTED_VIA_FOCUS = "muted-via-focus";
+ field public static final String STATUS_ON_HOLD = "on-hold";
+ field public static final String STATUS_PENDING = "pending";
+ field public static final String STATUS_SEND_ONLY = "sendonly";
+ field public static final String STATUS_SEND_RECV = "sendrecv";
+ field public static final String USER = "user";
+ field public final java.util.HashMap<java.lang.String,android.os.Bundle> mParticipants;
+ }
+
+ public final class ImsException extends java.lang.Exception {
+ ctor public ImsException(@Nullable String);
+ ctor public ImsException(@Nullable String, int);
+ ctor public ImsException(@Nullable String, int, @Nullable Throwable);
+ method public int getCode();
+ field public static final int CODE_ERROR_SERVICE_UNAVAILABLE = 1; // 0x1
+ field public static final int CODE_ERROR_UNSPECIFIED = 0; // 0x0
+ field public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2; // 0x2
+ }
+
+ public final class ImsExternalCallState implements android.os.Parcelable {
+ ctor public ImsExternalCallState(@NonNull String, @NonNull android.net.Uri, @Nullable android.net.Uri, boolean, int, int, boolean);
+ method public int describeContents();
+ method @NonNull public android.net.Uri getAddress();
+ method public int getCallId();
+ method public int getCallState();
+ method public int getCallType();
+ method @Nullable public android.net.Uri getLocalAddress();
+ method public boolean isCallHeld();
+ method public boolean isCallPullable();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CALL_STATE_CONFIRMED = 1; // 0x1
+ field public static final int CALL_STATE_TERMINATED = 2; // 0x2
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsExternalCallState> CREATOR;
+ }
+
+ public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
+ method @NonNull public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getFeatureState(@NonNull java.util.function.Consumer<java.lang.Integer>, @NonNull java.util.concurrent.Executor) throws android.telephony.ims.ImsException;
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getVoWiFiModeSetting();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getVoWiFiRoamingModeSetting();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isAdvancedCallingSettingEnabled();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isAvailable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void isSupported(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>) throws android.telephony.ims.ImsException;
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isTtyOverVolteEnabled();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isVoWiFiRoamingSettingEnabled();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isVoWiFiSettingEnabled();
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isVtSettingEnabled();
+ method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerMmTelCapabilityCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAdvancedCallingSettingEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setRttCapabilitySetting(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiModeSetting(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiNonPersistent(boolean, int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingModeSetting(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiRoamingSettingEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVoWiFiSettingEnabled(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setVtSettingEnabled(boolean);
+ method @Deprecated @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.ImsMmTelManager.RegistrationCallback);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterMmTelCapabilityCallback(@NonNull android.telephony.ims.ImsMmTelManager.CapabilityCallback);
+ field public static final int WIFI_MODE_CELLULAR_PREFERRED = 1; // 0x1
+ field public static final int WIFI_MODE_WIFI_ONLY = 0; // 0x0
+ field public static final int WIFI_MODE_WIFI_PREFERRED = 2; // 0x2
+ }
+
+ public static class ImsMmTelManager.CapabilityCallback {
+ ctor public ImsMmTelManager.CapabilityCallback();
+ method public void onCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
+ }
+
+ @Deprecated public static class ImsMmTelManager.RegistrationCallback extends android.telephony.ims.RegistrationManager.RegistrationCallback {
+ ctor @Deprecated public ImsMmTelManager.RegistrationCallback();
+ }
+
+ public final class ImsReasonInfo implements android.os.Parcelable {
+ ctor public ImsReasonInfo(int, int, String);
+ method public int describeContents();
+ method public int getCode();
+ method public int getExtraCode();
+ method public String getExtraMessage();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CODE_ACCESS_CLASS_BLOCKED = 1512; // 0x5e8
+ field public static final int CODE_ANSWERED_ELSEWHERE = 1014; // 0x3f6
+ field public static final int CODE_BLACKLISTED_CALL_ID = 506; // 0x1fa
+ field public static final int CODE_CALL_BARRED = 240; // 0xf0
+ field public static final int CODE_CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE = 1100; // 0x44c
+ field public static final int CODE_CALL_END_CAUSE_CALL_PULL = 1016; // 0x3f8
+ field public static final int CODE_CALL_PULL_OUT_OF_SYNC = 1015; // 0x3f7
+ field public static final int CODE_DATA_DISABLED = 1406; // 0x57e
+ field public static final int CODE_DATA_LIMIT_REACHED = 1405; // 0x57d
+ field public static final int CODE_DIAL_MODIFIED_TO_DIAL = 246; // 0xf6
+ field public static final int CODE_DIAL_MODIFIED_TO_DIAL_VIDEO = 247; // 0xf7
+ field public static final int CODE_DIAL_MODIFIED_TO_SS = 245; // 0xf5
+ field public static final int CODE_DIAL_MODIFIED_TO_USSD = 244; // 0xf4
+ field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_DIAL = 248; // 0xf8
+ field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_DIAL_VIDEO = 249; // 0xf9
+ field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_SS = 250; // 0xfa
+ field public static final int CODE_DIAL_VIDEO_MODIFIED_TO_USSD = 251; // 0xfb
+ field public static final int CODE_ECBM_NOT_SUPPORTED = 901; // 0x385
+ field public static final int CODE_EMERGENCY_PERM_FAILURE = 364; // 0x16c
+ field public static final int CODE_EMERGENCY_TEMP_FAILURE = 363; // 0x16b
+ field public static final int CODE_EPDG_TUNNEL_ESTABLISH_FAILURE = 1400; // 0x578
+ field public static final int CODE_EPDG_TUNNEL_LOST_CONNECTION = 1402; // 0x57a
+ field public static final int CODE_EPDG_TUNNEL_REKEY_FAILURE = 1401; // 0x579
+ field public static final int CODE_FDN_BLOCKED = 241; // 0xf1
+ field public static final int CODE_IKEV2_AUTH_FAILURE = 1408; // 0x580
+ field public static final int CODE_IMEI_NOT_ACCEPTED = 243; // 0xf3
+ field public static final int CODE_IWLAN_DPD_FAILURE = 1300; // 0x514
+ field public static final int CODE_LOCAL_CALL_BUSY = 142; // 0x8e
+ field public static final int CODE_LOCAL_CALL_CS_RETRY_REQUIRED = 146; // 0x92
+ field public static final int CODE_LOCAL_CALL_DECLINE = 143; // 0x8f
+ field public static final int CODE_LOCAL_CALL_EXCEEDED = 141; // 0x8d
+ field public static final int CODE_LOCAL_CALL_RESOURCE_RESERVATION_FAILED = 145; // 0x91
+ field public static final int CODE_LOCAL_CALL_TERMINATED = 148; // 0x94
+ field public static final int CODE_LOCAL_CALL_VCC_ON_PROGRESSING = 144; // 0x90
+ field public static final int CODE_LOCAL_CALL_VOLTE_RETRY_REQUIRED = 147; // 0x93
+ field public static final int CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE = 108; // 0x6c
+ field public static final int CODE_LOCAL_HO_NOT_FEASIBLE = 149; // 0x95
+ field public static final int CODE_LOCAL_ILLEGAL_ARGUMENT = 101; // 0x65
+ field public static final int CODE_LOCAL_ILLEGAL_STATE = 102; // 0x66
+ field public static final int CODE_LOCAL_IMS_SERVICE_DOWN = 106; // 0x6a
+ field public static final int CODE_LOCAL_INTERNAL_ERROR = 103; // 0x67
+ field public static final int CODE_LOCAL_LOW_BATTERY = 112; // 0x70
+ field public static final int CODE_LOCAL_NETWORK_IP_CHANGED = 124; // 0x7c
+ field public static final int CODE_LOCAL_NETWORK_NO_LTE_COVERAGE = 122; // 0x7a
+ field public static final int CODE_LOCAL_NETWORK_NO_SERVICE = 121; // 0x79
+ field public static final int CODE_LOCAL_NETWORK_ROAMING = 123; // 0x7b
+ field public static final int CODE_LOCAL_NOT_REGISTERED = 132; // 0x84
+ field public static final int CODE_LOCAL_NO_PENDING_CALL = 107; // 0x6b
+ field public static final int CODE_LOCAL_POWER_OFF = 111; // 0x6f
+ field public static final int CODE_LOCAL_SERVICE_UNAVAILABLE = 131; // 0x83
+ field public static final int CODE_LOW_BATTERY = 505; // 0x1f9
+ field public static final int CODE_MAXIMUM_NUMBER_OF_CALLS_REACHED = 1403; // 0x57b
+ field public static final int CODE_MEDIA_INIT_FAILED = 401; // 0x191
+ field public static final int CODE_MEDIA_NOT_ACCEPTABLE = 403; // 0x193
+ field public static final int CODE_MEDIA_NO_DATA = 402; // 0x192
+ field public static final int CODE_MEDIA_UNSPECIFIED = 404; // 0x194
+ field public static final int CODE_MULTIENDPOINT_NOT_SUPPORTED = 902; // 0x386
+ field public static final int CODE_NETWORK_DETACH = 1513; // 0x5e9
+ field public static final int CODE_NETWORK_REJECT = 1504; // 0x5e0
+ field public static final int CODE_NETWORK_RESP_TIMEOUT = 1503; // 0x5df
+ field public static final int CODE_NO_CSFB_IN_CS_ROAM = 1516; // 0x5ec
+ field public static final int CODE_NO_VALID_SIM = 1501; // 0x5dd
+ field public static final int CODE_OEM_CAUSE_1 = 61441; // 0xf001
+ field public static final int CODE_OEM_CAUSE_10 = 61450; // 0xf00a
+ field public static final int CODE_OEM_CAUSE_11 = 61451; // 0xf00b
+ field public static final int CODE_OEM_CAUSE_12 = 61452; // 0xf00c
+ field public static final int CODE_OEM_CAUSE_13 = 61453; // 0xf00d
+ field public static final int CODE_OEM_CAUSE_14 = 61454; // 0xf00e
+ field public static final int CODE_OEM_CAUSE_15 = 61455; // 0xf00f
+ field public static final int CODE_OEM_CAUSE_2 = 61442; // 0xf002
+ field public static final int CODE_OEM_CAUSE_3 = 61443; // 0xf003
+ field public static final int CODE_OEM_CAUSE_4 = 61444; // 0xf004
+ field public static final int CODE_OEM_CAUSE_5 = 61445; // 0xf005
+ field public static final int CODE_OEM_CAUSE_6 = 61446; // 0xf006
+ field public static final int CODE_OEM_CAUSE_7 = 61447; // 0xf007
+ field public static final int CODE_OEM_CAUSE_8 = 61448; // 0xf008
+ field public static final int CODE_OEM_CAUSE_9 = 61449; // 0xf009
+ field public static final int CODE_RADIO_ACCESS_FAILURE = 1505; // 0x5e1
+ field public static final int CODE_RADIO_INTERNAL_ERROR = 1502; // 0x5de
+ field public static final int CODE_RADIO_LINK_FAILURE = 1506; // 0x5e2
+ field public static final int CODE_RADIO_LINK_LOST = 1507; // 0x5e3
+ field public static final int CODE_RADIO_OFF = 1500; // 0x5dc
+ field public static final int CODE_RADIO_RELEASE_ABNORMAL = 1511; // 0x5e7
+ field public static final int CODE_RADIO_RELEASE_NORMAL = 1510; // 0x5e6
+ field public static final int CODE_RADIO_SETUP_FAILURE = 1509; // 0x5e5
+ field public static final int CODE_RADIO_UPLINK_FAILURE = 1508; // 0x5e4
+ field public static final int CODE_REGISTRATION_ERROR = 1000; // 0x3e8
+ field public static final int CODE_REJECTED_ELSEWHERE = 1017; // 0x3f9
+ field public static final int CODE_REJECT_1X_COLLISION = 1603; // 0x643
+ field public static final int CODE_REJECT_CALL_ON_OTHER_SUB = 1602; // 0x642
+ field public static final int CODE_REJECT_CALL_TYPE_NOT_ALLOWED = 1605; // 0x645
+ field public static final int CODE_REJECT_CONFERENCE_TTY_NOT_ALLOWED = 1617; // 0x651
+ field public static final int CODE_REJECT_INTERNAL_ERROR = 1612; // 0x64c
+ field public static final int CODE_REJECT_MAX_CALL_LIMIT_REACHED = 1608; // 0x648
+ field public static final int CODE_REJECT_ONGOING_CALL_SETUP = 1607; // 0x647
+ field public static final int CODE_REJECT_ONGOING_CALL_TRANSFER = 1611; // 0x64b
+ field public static final int CODE_REJECT_ONGOING_CALL_UPGRADE = 1616; // 0x650
+ field public static final int CODE_REJECT_ONGOING_CALL_WAITING_DISABLED = 1601; // 0x641
+ field public static final int CODE_REJECT_ONGOING_CONFERENCE_CALL = 1618; // 0x652
+ field public static final int CODE_REJECT_ONGOING_CS_CALL = 1621; // 0x655
+ field public static final int CODE_REJECT_ONGOING_E911_CALL = 1606; // 0x646
+ field public static final int CODE_REJECT_ONGOING_ENCRYPTED_CALL = 1620; // 0x654
+ field public static final int CODE_REJECT_ONGOING_HANDOVER = 1614; // 0x64e
+ field public static final int CODE_REJECT_QOS_FAILURE = 1613; // 0x64d
+ field public static final int CODE_REJECT_SERVICE_NOT_REGISTERED = 1604; // 0x644
+ field public static final int CODE_REJECT_UNKNOWN = 1600; // 0x640
+ field public static final int CODE_REJECT_UNSUPPORTED_SDP_HEADERS = 1610; // 0x64a
+ field public static final int CODE_REJECT_UNSUPPORTED_SIP_HEADERS = 1609; // 0x649
+ field public static final int CODE_REJECT_VT_AVPF_NOT_ALLOWED = 1619; // 0x653
+ field public static final int CODE_REJECT_VT_TTY_NOT_ALLOWED = 1615; // 0x64f
+ field public static final int CODE_REMOTE_CALL_DECLINE = 1404; // 0x57c
+ field public static final int CODE_SESSION_MODIFICATION_FAILED = 1517; // 0x5ed
+ field public static final int CODE_SIP_ALTERNATE_EMERGENCY_CALL = 1514; // 0x5ea
+ field public static final int CODE_SIP_AMBIGUOUS = 376; // 0x178
+ field public static final int CODE_SIP_BAD_ADDRESS = 337; // 0x151
+ field public static final int CODE_SIP_BAD_REQUEST = 331; // 0x14b
+ field public static final int CODE_SIP_BUSY = 338; // 0x152
+ field public static final int CODE_SIP_CALL_OR_TRANS_DOES_NOT_EXIST = 372; // 0x174
+ field public static final int CODE_SIP_CLIENT_ERROR = 342; // 0x156
+ field public static final int CODE_SIP_EXTENSION_REQUIRED = 370; // 0x172
+ field public static final int CODE_SIP_FORBIDDEN = 332; // 0x14c
+ field public static final int CODE_SIP_GLOBAL_ERROR = 362; // 0x16a
+ field public static final int CODE_SIP_INTERVAL_TOO_BRIEF = 371; // 0x173
+ field public static final int CODE_SIP_LOOP_DETECTED = 373; // 0x175
+ field public static final int CODE_SIP_METHOD_NOT_ALLOWED = 366; // 0x16e
+ field public static final int CODE_SIP_NOT_ACCEPTABLE = 340; // 0x154
+ field public static final int CODE_SIP_NOT_FOUND = 333; // 0x14d
+ field public static final int CODE_SIP_NOT_REACHABLE = 341; // 0x155
+ field public static final int CODE_SIP_NOT_SUPPORTED = 334; // 0x14e
+ field public static final int CODE_SIP_PROXY_AUTHENTICATION_REQUIRED = 367; // 0x16f
+ field public static final int CODE_SIP_REDIRECTED = 321; // 0x141
+ field public static final int CODE_SIP_REQUEST_CANCELLED = 339; // 0x153
+ field public static final int CODE_SIP_REQUEST_ENTITY_TOO_LARGE = 368; // 0x170
+ field public static final int CODE_SIP_REQUEST_PENDING = 377; // 0x179
+ field public static final int CODE_SIP_REQUEST_TIMEOUT = 335; // 0x14f
+ field public static final int CODE_SIP_REQUEST_URI_TOO_LARGE = 369; // 0x171
+ field public static final int CODE_SIP_SERVER_ERROR = 354; // 0x162
+ field public static final int CODE_SIP_SERVER_INTERNAL_ERROR = 351; // 0x15f
+ field public static final int CODE_SIP_SERVER_TIMEOUT = 353; // 0x161
+ field public static final int CODE_SIP_SERVICE_UNAVAILABLE = 352; // 0x160
+ field public static final int CODE_SIP_TEMPRARILY_UNAVAILABLE = 336; // 0x150
+ field public static final int CODE_SIP_TOO_MANY_HOPS = 374; // 0x176
+ field public static final int CODE_SIP_TRANSACTION_DOES_NOT_EXIST = 343; // 0x157
+ field public static final int CODE_SIP_UNDECIPHERABLE = 378; // 0x17a
+ field public static final int CODE_SIP_USER_MARKED_UNWANTED = 365; // 0x16d
+ field public static final int CODE_SIP_USER_REJECTED = 361; // 0x169
+ field public static final int CODE_SUPP_SVC_CANCELLED = 1202; // 0x4b2
+ field public static final int CODE_SUPP_SVC_FAILED = 1201; // 0x4b1
+ field public static final int CODE_SUPP_SVC_REINVITE_COLLISION = 1203; // 0x4b3
+ field public static final int CODE_TIMEOUT_1XX_WAITING = 201; // 0xc9
+ field public static final int CODE_TIMEOUT_NO_ANSWER = 202; // 0xca
+ field public static final int CODE_TIMEOUT_NO_ANSWER_CALL_UPDATE = 203; // 0xcb
+ field public static final int CODE_UNSPECIFIED = 0; // 0x0
+ field public static final int CODE_USER_CANCELLED_SESSION_MODIFICATION = 512; // 0x200
+ field public static final int CODE_USER_DECLINE = 504; // 0x1f8
+ field public static final int CODE_USER_IGNORE = 503; // 0x1f7
+ field public static final int CODE_USER_NOANSWER = 502; // 0x1f6
+ field public static final int CODE_USER_REJECTED_SESSION_MODIFICATION = 511; // 0x1ff
+ field public static final int CODE_USER_TERMINATED = 501; // 0x1f5
+ field public static final int CODE_USER_TERMINATED_BY_REMOTE = 510; // 0x1fe
+ field public static final int CODE_UT_CB_PASSWORD_MISMATCH = 821; // 0x335
+ field public static final int CODE_UT_NETWORK_ERROR = 804; // 0x324
+ field public static final int CODE_UT_NOT_SUPPORTED = 801; // 0x321
+ field public static final int CODE_UT_OPERATION_NOT_ALLOWED = 803; // 0x323
+ field public static final int CODE_UT_SERVICE_UNAVAILABLE = 802; // 0x322
+ field public static final int CODE_UT_SS_MODIFIED_TO_DIAL = 822; // 0x336
+ field public static final int CODE_UT_SS_MODIFIED_TO_DIAL_VIDEO = 825; // 0x339
+ field public static final int CODE_UT_SS_MODIFIED_TO_SS = 824; // 0x338
+ field public static final int CODE_UT_SS_MODIFIED_TO_USSD = 823; // 0x337
+ field public static final int CODE_WIFI_LOST = 1407; // 0x57f
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsReasonInfo> CREATOR;
+ field public static final int EXTRA_CODE_CALL_RETRY_BY_SETTINGS = 3; // 0x3
+ field public static final int EXTRA_CODE_CALL_RETRY_NORMAL = 1; // 0x1
+ field public static final int EXTRA_CODE_CALL_RETRY_SILENT_REDIAL = 2; // 0x2
+ field public static final String EXTRA_MSG_SERVICE_NOT_AUTHORIZED = "Forbidden. Not Authorized for Service";
+ }
+
+ public class ImsService extends android.app.Service {
+ ctor public ImsService();
+ method public android.telephony.ims.feature.MmTelFeature createMmTelFeature(int);
+ method public android.telephony.ims.feature.RcsFeature createRcsFeature(int);
+ method public void disableIms(int);
+ method public void enableIms(int);
+ method public android.telephony.ims.stub.ImsConfigImplBase getConfig(int);
+ method public android.telephony.ims.stub.ImsRegistrationImplBase getRegistration(int);
+ method public final void onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) throws android.os.RemoteException;
+ method public android.telephony.ims.stub.ImsFeatureConfiguration querySupportedImsFeatures();
+ method public void readyForFeatureCreation();
+ }
+
+ public final class ImsSsData implements android.os.Parcelable {
+ ctor public ImsSsData(int, int, int, int, int);
+ method public int describeContents();
+ method @Nullable public java.util.List<android.telephony.ims.ImsCallForwardInfo> getCallForwardInfo();
+ method public int getRequestType();
+ method public int getResult();
+ method public int getServiceClass();
+ method public int getServiceType();
+ method @NonNull public java.util.List<android.telephony.ims.ImsSsInfo> getSuppServiceInfo();
+ method public int getTeleserviceType();
+ method public boolean isTypeBarring();
+ method public boolean isTypeCf();
+ method public boolean isTypeClip();
+ method public boolean isTypeClir();
+ method public boolean isTypeColp();
+ method public boolean isTypeColr();
+ method public boolean isTypeCw();
+ method public boolean isTypeIcb();
+ method public boolean isTypeInterrogation();
+ method public boolean isTypeUnConditional();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsData> CREATOR;
+ field public static final int RESULT_SUCCESS = 0; // 0x0
+ field public static final int SERVICE_CLASS_DATA = 2; // 0x2
+ field public static final int SERVICE_CLASS_DATA_CIRCUIT_ASYNC = 32; // 0x20
+ field public static final int SERVICE_CLASS_DATA_CIRCUIT_SYNC = 16; // 0x10
+ field public static final int SERVICE_CLASS_DATA_PACKET_ACCESS = 64; // 0x40
+ field public static final int SERVICE_CLASS_DATA_PAD = 128; // 0x80
+ field public static final int SERVICE_CLASS_FAX = 4; // 0x4
+ field public static final int SERVICE_CLASS_NONE = 0; // 0x0
+ field public static final int SERVICE_CLASS_SMS = 8; // 0x8
+ field public static final int SERVICE_CLASS_VOICE = 1; // 0x1
+ field public static final int SS_ACTIVATION = 0; // 0x0
+ field public static final int SS_ALL_BARRING = 18; // 0x12
+ field public static final int SS_ALL_DATA_TELESERVICES = 3; // 0x3
+ field public static final int SS_ALL_TELESERVICES_EXCEPT_SMS = 5; // 0x5
+ field public static final int SS_ALL_TELESEVICES = 1; // 0x1
+ field public static final int SS_ALL_TELE_AND_BEARER_SERVICES = 0; // 0x0
+ field public static final int SS_BAIC = 16; // 0x10
+ field public static final int SS_BAIC_ROAMING = 17; // 0x11
+ field public static final int SS_BAOC = 13; // 0xd
+ field public static final int SS_BAOIC = 14; // 0xe
+ field public static final int SS_BAOIC_EXC_HOME = 15; // 0xf
+ field public static final int SS_CFU = 0; // 0x0
+ field public static final int SS_CFUT = 6; // 0x6
+ field public static final int SS_CF_ALL = 4; // 0x4
+ field public static final int SS_CF_ALL_CONDITIONAL = 5; // 0x5
+ field public static final int SS_CF_BUSY = 1; // 0x1
+ field public static final int SS_CF_NOT_REACHABLE = 3; // 0x3
+ field public static final int SS_CF_NO_REPLY = 2; // 0x2
+ field public static final int SS_CLIP = 7; // 0x7
+ field public static final int SS_CLIR = 8; // 0x8
+ field public static final int SS_CNAP = 11; // 0xb
+ field public static final int SS_COLP = 9; // 0x9
+ field public static final int SS_COLR = 10; // 0xa
+ field public static final int SS_DEACTIVATION = 1; // 0x1
+ field public static final int SS_ERASURE = 4; // 0x4
+ field public static final int SS_INCOMING_BARRING = 20; // 0x14
+ field public static final int SS_INCOMING_BARRING_ANONYMOUS = 22; // 0x16
+ field public static final int SS_INCOMING_BARRING_DN = 21; // 0x15
+ field public static final int SS_INTERROGATION = 2; // 0x2
+ field public static final int SS_OUTGOING_BARRING = 19; // 0x13
+ field public static final int SS_REGISTRATION = 3; // 0x3
+ field public static final int SS_SMS_SERVICES = 4; // 0x4
+ field public static final int SS_TELEPHONY = 2; // 0x2
+ field public static final int SS_WAIT = 12; // 0xc
+ }
+
+ public static final class ImsSsData.Builder {
+ ctor public ImsSsData.Builder(int, int, int, int, int);
+ method @NonNull public android.telephony.ims.ImsSsData build();
+ method @NonNull public android.telephony.ims.ImsSsData.Builder setCallForwardingInfo(@NonNull java.util.List<android.telephony.ims.ImsCallForwardInfo>);
+ method @NonNull public android.telephony.ims.ImsSsData.Builder setSuppServiceInfo(@NonNull java.util.List<android.telephony.ims.ImsSsInfo>);
+ }
+
+ public final class ImsSsInfo implements android.os.Parcelable {
+ ctor @Deprecated public ImsSsInfo(int, @Nullable String);
+ method public int describeContents();
+ method public int getClirInterrogationStatus();
+ method public int getClirOutgoingState();
+ method @Deprecated public String getIcbNum();
+ method @Nullable public String getIncomingCommunicationBarringNumber();
+ method public int getProvisionStatus();
+ method public int getStatus();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int CLIR_OUTGOING_DEFAULT = 0; // 0x0
+ field public static final int CLIR_OUTGOING_INVOCATION = 1; // 0x1
+ field public static final int CLIR_OUTGOING_SUPPRESSION = 2; // 0x2
+ field public static final int CLIR_STATUS_NOT_PROVISIONED = 0; // 0x0
+ field public static final int CLIR_STATUS_PROVISIONED_PERMANENT = 1; // 0x1
+ field public static final int CLIR_STATUS_TEMPORARILY_ALLOWED = 4; // 0x4
+ field public static final int CLIR_STATUS_TEMPORARILY_RESTRICTED = 3; // 0x3
+ field public static final int CLIR_STATUS_UNKNOWN = 2; // 0x2
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSsInfo> CREATOR;
+ field public static final int DISABLED = 0; // 0x0
+ field public static final int ENABLED = 1; // 0x1
+ field public static final int NOT_REGISTERED = -1; // 0xffffffff
+ field public static final int SERVICE_NOT_PROVISIONED = 0; // 0x0
+ field public static final int SERVICE_PROVISIONED = 1; // 0x1
+ field public static final int SERVICE_PROVISIONING_UNKNOWN = -1; // 0xffffffff
+ }
+
+ public static final class ImsSsInfo.Builder {
+ ctor public ImsSsInfo.Builder(int);
+ method @NonNull public android.telephony.ims.ImsSsInfo build();
+ method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirInterrogationStatus(int);
+ method @NonNull public android.telephony.ims.ImsSsInfo.Builder setClirOutgoingState(int);
+ method @NonNull public android.telephony.ims.ImsSsInfo.Builder setIncomingCommunicationBarringNumber(@NonNull String);
+ method @NonNull public android.telephony.ims.ImsSsInfo.Builder setProvisionStatus(int);
+ }
+
+ public final class ImsStreamMediaProfile implements android.os.Parcelable {
+ ctor public ImsStreamMediaProfile(int, int, int, int, int);
+ method public void copyFrom(android.telephony.ims.ImsStreamMediaProfile);
+ method public int describeContents();
+ method public int getAudioDirection();
+ method public int getAudioQuality();
+ method public int getRttMode();
+ method public int getVideoDirection();
+ method public int getVideoQuality();
+ method public boolean isReceivingRttAudio();
+ method public boolean isRttCall();
+ method public void setReceivingRttAudio(boolean);
+ method public void setRttMode(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int AUDIO_QUALITY_AMR = 1; // 0x1
+ field public static final int AUDIO_QUALITY_AMR_WB = 2; // 0x2
+ field public static final int AUDIO_QUALITY_EVRC = 4; // 0x4
+ field public static final int AUDIO_QUALITY_EVRC_B = 5; // 0x5
+ field public static final int AUDIO_QUALITY_EVRC_NW = 7; // 0x7
+ field public static final int AUDIO_QUALITY_EVRC_WB = 6; // 0x6
+ field public static final int AUDIO_QUALITY_EVS_FB = 20; // 0x14
+ field public static final int AUDIO_QUALITY_EVS_NB = 17; // 0x11
+ field public static final int AUDIO_QUALITY_EVS_SWB = 19; // 0x13
+ field public static final int AUDIO_QUALITY_EVS_WB = 18; // 0x12
+ field public static final int AUDIO_QUALITY_G711A = 13; // 0xd
+ field public static final int AUDIO_QUALITY_G711AB = 15; // 0xf
+ field public static final int AUDIO_QUALITY_G711U = 11; // 0xb
+ field public static final int AUDIO_QUALITY_G722 = 14; // 0xe
+ field public static final int AUDIO_QUALITY_G723 = 12; // 0xc
+ field public static final int AUDIO_QUALITY_G729 = 16; // 0x10
+ field public static final int AUDIO_QUALITY_GSM_EFR = 8; // 0x8
+ field public static final int AUDIO_QUALITY_GSM_FR = 9; // 0x9
+ field public static final int AUDIO_QUALITY_GSM_HR = 10; // 0xa
+ field public static final int AUDIO_QUALITY_NONE = 0; // 0x0
+ field public static final int AUDIO_QUALITY_QCELP13K = 3; // 0x3
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsStreamMediaProfile> CREATOR;
+ field public static final int DIRECTION_INACTIVE = 0; // 0x0
+ field public static final int DIRECTION_INVALID = -1; // 0xffffffff
+ field public static final int DIRECTION_RECEIVE = 1; // 0x1
+ field public static final int DIRECTION_SEND = 2; // 0x2
+ field public static final int DIRECTION_SEND_RECEIVE = 3; // 0x3
+ field public static final int RTT_MODE_DISABLED = 0; // 0x0
+ field public static final int RTT_MODE_FULL = 1; // 0x1
+ field public static final int VIDEO_QUALITY_NONE = 0; // 0x0
+ field public static final int VIDEO_QUALITY_QCIF = 1; // 0x1
+ field public static final int VIDEO_QUALITY_QVGA_LANDSCAPE = 2; // 0x2
+ field public static final int VIDEO_QUALITY_QVGA_PORTRAIT = 4; // 0x4
+ field public static final int VIDEO_QUALITY_VGA_LANDSCAPE = 8; // 0x8
+ field public static final int VIDEO_QUALITY_VGA_PORTRAIT = 16; // 0x10
+ }
+
+ public final class ImsSuppServiceNotification implements android.os.Parcelable {
+ ctor public ImsSuppServiceNotification(int, int, int, int, String, String[]);
+ method public int describeContents();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.ImsSuppServiceNotification> CREATOR;
+ field public final int code;
+ field public final String[] history;
+ field public final int index;
+ field public final int notificationType;
+ field public final String number;
+ field public final int type;
+ }
+
+ public class ImsUtListener {
+ method public void onLineIdentificationSupplementaryServiceResponse(int, @NonNull android.telephony.ims.ImsSsInfo);
+ method public void onSupplementaryServiceIndication(android.telephony.ims.ImsSsData);
+ method public void onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]);
+ method public void onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]);
+ method public void onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]);
+ method @Deprecated public void onUtConfigurationQueried(int, android.os.Bundle);
+ method public void onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo);
+ method public void onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo);
+ method public void onUtConfigurationUpdated(int);
+ field @Deprecated public static final String BUNDLE_KEY_CLIR = "queryClir";
+ field @Deprecated public static final String BUNDLE_KEY_SSINFO = "imsSsInfo";
+ }
+
+ public abstract class ImsVideoCallProvider {
+ ctor public ImsVideoCallProvider();
+ method public void changeCallDataUsage(long);
+ method public void changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities);
+ method public void changePeerDimensions(int, int);
+ method public void changeVideoQuality(int);
+ method public void handleCallSessionEvent(int);
+ method public abstract void onRequestCallDataUsage();
+ method public abstract void onRequestCameraCapabilities();
+ method public abstract void onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile);
+ method public abstract void onSendSessionModifyResponse(android.telecom.VideoProfile);
+ method public abstract void onSetCamera(String);
+ method public void onSetCamera(String, int);
+ method public abstract void onSetDeviceOrientation(int);
+ method public abstract void onSetDisplaySurface(android.view.Surface);
+ method public abstract void onSetPauseImage(android.net.Uri);
+ method public abstract void onSetPreviewSurface(android.view.Surface);
+ method public abstract void onSetZoom(float);
+ method public void receiveSessionModifyRequest(android.telecom.VideoProfile);
+ method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
+ }
+
+ public class ProvisioningManager {
+ method @NonNull public static android.telephony.ims.ProvisioningManager createForSubscriptionId(int);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public int getProvisioningIntValue(int);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public boolean getProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method @Nullable @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") @WorkerThread public String getProvisioningStringValue(int);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerProvisioningChangedCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.ProvisioningManager.Callback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningIntValue(int, int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void setProvisioningStatusForCapability(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int, boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public int setProvisioningStringValue(int, @NonNull String);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterProvisioningChangedCallback(@NonNull android.telephony.ims.ProvisioningManager.Callback);
+ field public static final int KEY_VOICE_OVER_WIFI_MODE_OVERRIDE = 27; // 0x1b
+ field public static final int KEY_VOICE_OVER_WIFI_ROAMING_ENABLED_OVERRIDE = 26; // 0x1a
+ field public static final int PROVISIONING_VALUE_DISABLED = 0; // 0x0
+ field public static final int PROVISIONING_VALUE_ENABLED = 1; // 0x1
+ field public static final String STRING_QUERY_RESULT_ERROR_GENERIC = "STRING_QUERY_RESULT_ERROR_GENERIC";
+ field public static final String STRING_QUERY_RESULT_ERROR_NOT_READY = "STRING_QUERY_RESULT_ERROR_NOT_READY";
+ }
+
+ public static class ProvisioningManager.Callback {
+ ctor public ProvisioningManager.Callback();
+ method public void onProvisioningIntChanged(int, int);
+ method public void onProvisioningStringChanged(int, @NonNull String);
+ }
+
+ public interface RegistrationManager {
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void registerImsRegistrationCallback(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RegistrationManager.RegistrationCallback) throws android.telephony.ims.ImsException;
+ method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void unregisterImsRegistrationCallback(@NonNull android.telephony.ims.RegistrationManager.RegistrationCallback);
+ field public static final int REGISTRATION_STATE_NOT_REGISTERED = 0; // 0x0
+ field public static final int REGISTRATION_STATE_REGISTERED = 2; // 0x2
+ field public static final int REGISTRATION_STATE_REGISTERING = 1; // 0x1
+ }
+
+ public static class RegistrationManager.RegistrationCallback {
+ ctor public RegistrationManager.RegistrationCallback();
+ method public void onRegistered(int);
+ method public void onRegistering(int);
+ method public void onTechnologyChangeFailed(int, @Nullable android.telephony.ims.ImsReasonInfo);
+ method public void onUnregistered(@Nullable android.telephony.ims.ImsReasonInfo);
+ }
+
+}
+
+package android.telephony.ims.feature {
+
+ public final class CapabilityChangeRequest implements android.os.Parcelable {
+ method public void addCapabilitiesToDisableForTech(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method public void addCapabilitiesToEnableForTech(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method public int describeContents();
+ method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToDisable();
+ method public java.util.List<android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair> getCapabilitiesToEnable();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.feature.CapabilityChangeRequest> CREATOR;
+ }
+
+ public static class CapabilityChangeRequest.CapabilityPair {
+ ctor public CapabilityChangeRequest.CapabilityPair(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method @android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability public int getCapability();
+ method public int getRadioTech();
+ }
+
+ public abstract class ImsFeature {
+ ctor public ImsFeature();
+ method public abstract void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+ method public final int getSlotIndex();
+ method public abstract void onFeatureReady();
+ method public abstract void onFeatureRemoved();
+ method public final void setFeatureState(int);
+ field public static final int CAPABILITY_ERROR_GENERIC = -1; // 0xffffffff
+ field public static final int CAPABILITY_SUCCESS = 0; // 0x0
+ field public static final int FEATURE_EMERGENCY_MMTEL = 0; // 0x0
+ field public static final int FEATURE_MMTEL = 1; // 0x1
+ field public static final int FEATURE_RCS = 2; // 0x2
+ field public static final int STATE_INITIALIZING = 1; // 0x1
+ field public static final int STATE_READY = 2; // 0x2
+ field public static final int STATE_UNAVAILABLE = 0; // 0x0
+ }
+
+ @Deprecated public static class ImsFeature.Capabilities {
+ field @Deprecated protected int mCapabilities;
+ }
+
+ protected static class ImsFeature.CapabilityCallbackProxy {
+ method public void onChangeCapabilityConfigurationError(int, int, int);
+ }
+
+ public class MmTelFeature extends android.telephony.ims.feature.ImsFeature {
+ ctor public MmTelFeature();
+ method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+ method @Nullable public android.telephony.ims.ImsCallProfile createCallProfile(int, int);
+ method @Nullable public android.telephony.ims.stub.ImsCallSessionImplBase createCallSession(@NonNull android.telephony.ims.ImsCallProfile);
+ method @NonNull public android.telephony.ims.stub.ImsEcbmImplBase getEcbm();
+ method @NonNull public android.telephony.ims.stub.ImsMultiEndpointImplBase getMultiEndpoint();
+ method @NonNull public android.telephony.ims.stub.ImsSmsImplBase getSmsImplementation();
+ method @NonNull public android.telephony.ims.stub.ImsUtImplBase getUt();
+ method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.MmTelFeature.MmTelCapabilities);
+ method public final void notifyIncomingCall(@NonNull android.telephony.ims.stub.ImsCallSessionImplBase, @NonNull android.os.Bundle);
+ method public final void notifyRejectedCall(@NonNull android.telephony.ims.ImsCallProfile, @NonNull android.telephony.ims.ImsReasonInfo);
+ method public final void notifyVoiceMessageCountUpdate(int);
+ method public void onFeatureReady();
+ method public void onFeatureRemoved();
+ method public boolean queryCapabilityConfiguration(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int, int);
+ method public final android.telephony.ims.feature.MmTelFeature.MmTelCapabilities queryCapabilityStatus();
+ method public void setUiTtyMode(int, @Nullable android.os.Message);
+ method @android.telephony.ims.feature.MmTelFeature.ProcessCallResult public int shouldProcessCall(@NonNull String[]);
+ field public static final String EXTRA_IS_UNKNOWN_CALL = "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
+ field public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD";
+ field public static final int PROCESS_CALL_CSFB = 1; // 0x1
+ field public static final int PROCESS_CALL_IMS = 0; // 0x0
+ }
+
+ public static class MmTelFeature.MmTelCapabilities extends android.telephony.ims.feature.ImsFeature.Capabilities {
+ ctor public MmTelFeature.MmTelCapabilities();
+ ctor @Deprecated public MmTelFeature.MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities);
+ ctor public MmTelFeature.MmTelCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
+ method public final void addCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
+ method public final boolean isCapable(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
+ method public final void removeCapabilities(@android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability int);
+ field public static final int CAPABILITY_TYPE_SMS = 8; // 0x8
+ field public static final int CAPABILITY_TYPE_UT = 4; // 0x4
+ field public static final int CAPABILITY_TYPE_VIDEO = 2; // 0x2
+ field public static final int CAPABILITY_TYPE_VOICE = 1; // 0x1
+ }
+
+ @IntDef(flag=true, value={android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT, android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_SMS}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MmTelFeature.MmTelCapabilities.MmTelCapability {
+ }
+
+ @IntDef(flag=true, value={android.telephony.ims.feature.MmTelFeature.PROCESS_CALL_IMS, android.telephony.ims.feature.MmTelFeature.PROCESS_CALL_CSFB}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface MmTelFeature.ProcessCallResult {
+ }
+
+ public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
+ ctor public RcsFeature();
+ method public void changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+ method public void onFeatureReady();
+ method public void onFeatureRemoved();
+ }
+
+}
+
+package android.telephony.ims.stub {
+
+ public class ImsCallSessionImplBase implements java.lang.AutoCloseable {
+ ctor public ImsCallSessionImplBase();
+ method public void accept(int, android.telephony.ims.ImsStreamMediaProfile);
+ method public void close();
+ method public void deflect(String);
+ method public void extendToConference(String[]);
+ method public String getCallId();
+ method public android.telephony.ims.ImsCallProfile getCallProfile();
+ method public android.telephony.ims.ImsVideoCallProvider getImsVideoCallProvider();
+ method public android.telephony.ims.ImsCallProfile getLocalCallProfile();
+ method public String getProperty(String);
+ method public android.telephony.ims.ImsCallProfile getRemoteCallProfile();
+ method public int getState();
+ method public void hold(android.telephony.ims.ImsStreamMediaProfile);
+ method public void inviteParticipants(String[]);
+ method public boolean isInCall();
+ method public boolean isMultiparty();
+ method public void merge();
+ method public void reject(int);
+ method public void removeParticipants(String[]);
+ method public void resume(android.telephony.ims.ImsStreamMediaProfile);
+ method public void sendDtmf(char, android.os.Message);
+ method public void sendRttMessage(String);
+ method public void sendRttModifyRequest(android.telephony.ims.ImsCallProfile);
+ method public void sendRttModifyResponse(boolean);
+ method public void sendUssd(String);
+ method public void setListener(android.telephony.ims.ImsCallSessionListener);
+ method public void setMute(boolean);
+ method public void start(String, android.telephony.ims.ImsCallProfile);
+ method public void startConference(String[], android.telephony.ims.ImsCallProfile);
+ method public void startDtmf(char);
+ method public void stopDtmf();
+ method public void terminate(int);
+ method public void update(int, android.telephony.ims.ImsStreamMediaProfile);
+ field public static final int USSD_MODE_NOTIFY = 0; // 0x0
+ field public static final int USSD_MODE_REQUEST = 1; // 0x1
+ }
+
+ public static class ImsCallSessionImplBase.State {
+ method public static String toString(int);
+ field public static final int ESTABLISHED = 4; // 0x4
+ field public static final int ESTABLISHING = 3; // 0x3
+ field public static final int IDLE = 0; // 0x0
+ field public static final int INITIATED = 1; // 0x1
+ field public static final int INVALID = -1; // 0xffffffff
+ field public static final int NEGOTIATING = 2; // 0x2
+ field public static final int REESTABLISHING = 6; // 0x6
+ field public static final int RENEGOTIATING = 5; // 0x5
+ field public static final int TERMINATED = 8; // 0x8
+ field public static final int TERMINATING = 7; // 0x7
+ }
+
+ public class ImsConfigImplBase {
+ ctor public ImsConfigImplBase();
+ method public int getConfigInt(int);
+ method public String getConfigString(int);
+ method public final void notifyProvisionedValueChanged(int, int);
+ method public final void notifyProvisionedValueChanged(int, String);
+ method public int setConfig(int, int);
+ method public int setConfig(int, String);
+ field public static final int CONFIG_RESULT_FAILED = 1; // 0x1
+ field public static final int CONFIG_RESULT_SUCCESS = 0; // 0x0
+ field public static final int CONFIG_RESULT_UNKNOWN = -1; // 0xffffffff
+ }
+
+ public class ImsEcbmImplBase {
+ ctor public ImsEcbmImplBase();
+ method public final void enteredEcbm();
+ method public void exitEmergencyCallbackMode();
+ method public final void exitedEcbm();
+ }
+
+ public final class ImsFeatureConfiguration implements android.os.Parcelable {
+ method public int describeContents();
+ method public java.util.Set<android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair> getServiceFeatures();
+ method public void writeToParcel(android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.stub.ImsFeatureConfiguration> CREATOR;
+ }
+
+ public static class ImsFeatureConfiguration.Builder {
+ ctor public ImsFeatureConfiguration.Builder();
+ method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int, int);
+ method public android.telephony.ims.stub.ImsFeatureConfiguration build();
+ }
+
+ public static final class ImsFeatureConfiguration.FeatureSlotPair {
+ ctor public ImsFeatureConfiguration.FeatureSlotPair(int, int);
+ field public final int featureType;
+ field public final int slotId;
+ }
+
+ public class ImsMultiEndpointImplBase {
+ ctor public ImsMultiEndpointImplBase();
+ method public final void onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>);
+ method public void requestImsExternalCallStateInfo();
+ }
+
+ public class ImsRegistrationImplBase {
+ ctor public ImsRegistrationImplBase();
+ method public final void onDeregistered(android.telephony.ims.ImsReasonInfo);
+ method public final void onRegistered(int);
+ method public final void onRegistering(int);
+ method public final void onSubscriberAssociatedUriChanged(android.net.Uri[]);
+ method public final void onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo);
+ field public static final int REGISTRATION_TECH_IWLAN = 1; // 0x1
+ field public static final int REGISTRATION_TECH_LTE = 0; // 0x0
+ field public static final int REGISTRATION_TECH_NONE = -1; // 0xffffffff
+ }
+
+ public class ImsSmsImplBase {
+ ctor public ImsSmsImplBase();
+ method public void acknowledgeSms(int, @IntRange(from=0, to=65535) int, int);
+ method public void acknowledgeSmsReport(int, @IntRange(from=0, to=65535) int, int);
+ method public String getSmsFormat();
+ method public void onReady();
+ method @Deprecated public final void onSendSmsResult(int, @IntRange(from=0, to=65535) int, int, int) throws java.lang.RuntimeException;
+ method public final void onSendSmsResultError(int, @IntRange(from=0, to=65535) int, int, int, int) throws java.lang.RuntimeException;
+ method public final void onSendSmsResultSuccess(int, @IntRange(from=0, to=65535) int) throws java.lang.RuntimeException;
+ method public final void onSmsReceived(int, String, byte[]) throws java.lang.RuntimeException;
+ method @Deprecated public final void onSmsStatusReportReceived(int, @IntRange(from=0, to=65535) int, String, byte[]) throws java.lang.RuntimeException;
+ method public final void onSmsStatusReportReceived(int, String, byte[]) throws java.lang.RuntimeException;
+ method public void sendSms(int, @IntRange(from=0, to=65535) int, String, String, boolean, byte[]);
+ field public static final int DELIVER_STATUS_ERROR_GENERIC = 2; // 0x2
+ field public static final int DELIVER_STATUS_ERROR_NO_MEMORY = 3; // 0x3
+ field public static final int DELIVER_STATUS_ERROR_REQUEST_NOT_SUPPORTED = 4; // 0x4
+ field public static final int DELIVER_STATUS_OK = 1; // 0x1
+ field public static final int RESULT_NO_NETWORK_ERROR = -1; // 0xffffffff
+ field public static final int SEND_STATUS_ERROR = 2; // 0x2
+ field public static final int SEND_STATUS_ERROR_FALLBACK = 4; // 0x4
+ field public static final int SEND_STATUS_ERROR_RETRY = 3; // 0x3
+ field public static final int SEND_STATUS_OK = 1; // 0x1
+ field public static final int STATUS_REPORT_STATUS_ERROR = 2; // 0x2
+ field public static final int STATUS_REPORT_STATUS_OK = 1; // 0x1
+ }
+
+ public class ImsUtImplBase {
+ ctor public ImsUtImplBase();
+ method public void close();
+ method public int queryCallBarring(int);
+ method public int queryCallBarringForServiceClass(int, int);
+ method public int queryCallForward(int, String);
+ method public int queryCallWaiting();
+ method public int queryClip();
+ method public int queryClir();
+ method public int queryColp();
+ method public int queryColr();
+ method public void setListener(android.telephony.ims.ImsUtListener);
+ method public int transact(android.os.Bundle);
+ method public int updateCallBarring(int, int, String[]);
+ method public int updateCallBarringForServiceClass(int, int, String[], int);
+ method public int updateCallForward(int, int, String, int, int);
+ method public int updateCallWaiting(boolean, int);
+ method public int updateClip(boolean);
+ method public int updateClir(int);
+ method public int updateColp(boolean);
+ method public int updateColr(int);
+ }
+
+}
+
package android.telephony.mbms {
public static class DownloadRequest.Builder {
diff --git a/api/test-lint-baseline.txt b/api/test-lint-baseline.txt
new file mode 100644
index 0000000..ba85ae6
--- /dev/null
+++ b/api/test-lint-baseline.txt
@@ -0,0 +1,2653 @@
+// Baseline format: 1.0
+AcronymName: android.app.NotificationChannel#isImportanceLockedByOEM():
+
+AcronymName: android.app.NotificationChannel#setImportanceLockedByOEM(boolean):
+
+
+
+ActionValue: android.location.Location#EXTRA_NO_GPS_LOCATION:
+
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_ADDITIONAL_CALL_INFO:
+ Inconsistent extra value; expected `android.telephony.ims.extra.ADDITIONAL_CALL_INFO`, was `AdditionalCallInfo`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CALL_RAT_TYPE:
+ Inconsistent extra value; expected `android.telephony.ims.extra.CALL_RAT_TYPE`, was `CallRadioTech`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CHILD_NUMBER:
+ Inconsistent extra value; expected `android.telephony.ims.extra.CHILD_NUMBER`, was `ChildNum`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CNA:
+ Inconsistent extra value; expected `android.telephony.ims.extra.CNA`, was `cna`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CNAP:
+ Inconsistent extra value; expected `android.telephony.ims.extra.CNAP`, was `cnap`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CODEC:
+ Inconsistent extra value; expected `android.telephony.ims.extra.CODEC`, was `Codec`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_DIALSTRING:
+ Inconsistent extra value; expected `android.telephony.ims.extra.DIALSTRING`, was `dialstring`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_DISPLAY_TEXT:
+ Inconsistent extra value; expected `android.telephony.ims.extra.DISPLAY_TEXT`, was `DisplayText`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_EMERGENCY_CALL:
+ Inconsistent extra value; expected `android.telephony.ims.extra.EMERGENCY_CALL`, was `e_call`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_IS_CALL_PULL:
+ Inconsistent extra value; expected `android.telephony.ims.extra.IS_CALL_PULL`, was `CallPull`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_OI:
+ Inconsistent extra value; expected `android.telephony.ims.extra.OI`, was `oi`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_OIR:
+ Inconsistent extra value; expected `android.telephony.ims.extra.OIR`, was `oir`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_REMOTE_URI:
+ Inconsistent extra value; expected `android.telephony.ims.extra.REMOTE_URI`, was `remote_uri`
+ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_USSD:
+ Inconsistent extra value; expected `android.telephony.ims.extra.USSD`, was `ussd`
+ActionValue: android.telephony.ims.ImsReasonInfo#EXTRA_MSG_SERVICE_NOT_AUTHORIZED:
+ Inconsistent extra value; expected `android.telephony.ims.extra.MSG_SERVICE_NOT_AUTHORIZED`, was `Forbidden. Not Authorized for Service`
+ActionValue: android.telephony.mbms.vendor.VendorUtils#ACTION_CLEANUP:
+
+ActionValue: android.telephony.mbms.vendor.VendorUtils#ACTION_DOWNLOAD_RESULT_INTERNAL:
+
+ActionValue: android.telephony.mbms.vendor.VendorUtils#ACTION_FILE_DESCRIPTOR_REQUEST:
+
+ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_FD_COUNT:
+
+ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_FINAL_URI:
+
+ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_FREE_URI_LIST:
+
+ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_PAUSED_LIST:
+
+ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_PAUSED_URI_LIST:
+
+ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_SERVICE_ID:
+
+ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_TEMP_FILES_IN_USE:
+
+ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_TEMP_FILE_ROOT:
+
+ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_TEMP_LIST:
+
+
+
+ArrayReturn: android.app.UiAutomation#executeShellCommandRw(String):
+
+ArrayReturn: android.location.GnssMeasurementsEvent#GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]) parameter #1:
+
+ArrayReturn: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #10:
+
+ArrayReturn: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #11:
+
+ArrayReturn: android.metrics.LogMaker#LogMaker(Object[]) parameter #0:
+
+ArrayReturn: android.metrics.LogMaker#deserialize(Object[]) parameter #0:
+
+ArrayReturn: android.metrics.LogMaker#serialize():
+
+ArrayReturn: android.net.TestNetworkManager#createTunInterface(android.net.LinkAddress[]) parameter #0:
+
+ArrayReturn: android.os.HwBlob#wrapArray(boolean[]):
+
+ArrayReturn: android.os.HwBlob#wrapArray(byte[]):
+
+ArrayReturn: android.os.HwBlob#wrapArray(double[]):
+
+ArrayReturn: android.os.HwBlob#wrapArray(float[]):
+
+ArrayReturn: android.os.HwBlob#wrapArray(int[]):
+
+ArrayReturn: android.os.HwBlob#wrapArray(long[]):
+
+ArrayReturn: android.os.HwBlob#wrapArray(short[]):
+
+ArrayReturn: android.os.NativeHandle#NativeHandle(java.io.FileDescriptor[], int[], boolean) parameter #0:
+
+ArrayReturn: android.os.NativeHandle#getFileDescriptors():
+
+ArrayReturn: android.security.keystore.AttestationUtils#attestDeviceIds(android.content.Context, int[], byte[]):
+
+ArrayReturn: android.telephony.ims.ImsUtListener#onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
+ Method parameter should be Collection<ImsSsInfo> (or subclass) instead of raw array; was `android.telephony.ims.ImsSsInfo[]`
+ArrayReturn: android.telephony.ims.ImsUtListener#onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]) parameter #1:
+ Method parameter should be Collection<ImsCallForwardInfo> (or subclass) instead of raw array; was `android.telephony.ims.ImsCallForwardInfo[]`
+ArrayReturn: android.telephony.ims.ImsUtListener#onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
+ Method parameter should be Collection<ImsSsInfo> (or subclass) instead of raw array; was `android.telephony.ims.ImsSsInfo[]`
+ArrayReturn: android.telephony.ims.stub.ImsRegistrationImplBase#onSubscriberAssociatedUriChanged(android.net.Uri[]) parameter #0:
+ Method parameter should be Collection<Uri> (or subclass) instead of raw array; was `android.net.Uri[]`
+ArrayReturn: android.view.FocusFinder#sort(android.view.View[], int, int, android.view.ViewGroup, boolean) parameter #0:
+
+ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions():
+
+ArrayReturn: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillOptions(CharSequence[]) parameter #0:
+
+ArrayReturn: android.view.inspector.InspectableProperty#enumMapping():
+
+ArrayReturn: android.view.inspector.InspectableProperty#flagMapping():
+
+
+
+AutoBoxing: android.os.HwBlob#wrapArray(byte[]):
+
+AutoBoxing: android.os.HwBlob#wrapArray(double[]):
+
+AutoBoxing: android.os.HwBlob#wrapArray(float[]):
+
+AutoBoxing: android.os.HwBlob#wrapArray(int[]):
+
+AutoBoxing: android.os.HwBlob#wrapArray(long[]):
+
+AutoBoxing: android.os.HwBlob#wrapArray(short[]):
+
+AutoBoxing: android.os.VintfObject#getTargetFrameworkCompatibilityMatrixVersion():
+
+
+
+BannedThrow: android.app.ActivityTaskManager#removeStacksInWindowingModes(int[]):
+
+BannedThrow: android.app.ActivityTaskManager#removeStacksWithActivityTypes(int[]):
+
+BannedThrow: android.app.ActivityTaskManager#setTaskWindowingMode(int, int, boolean):
+
+BannedThrow: android.app.ActivityTaskManager#setTaskWindowingModeSplitScreenPrimary(int, int, boolean, boolean, android.graphics.Rect, boolean):
+
+BannedThrow: android.media.audiofx.AudioEffect#getParameter(byte[], byte[]):
+
+BannedThrow: android.media.audiofx.AudioEffect#getParameter(int, byte[]):
+
+BannedThrow: android.media.audiofx.AudioEffect#getParameter(int, int[]):
+
+BannedThrow: android.media.audiofx.AudioEffect#getParameter(int, short[]):
+
+BannedThrow: android.media.audiofx.AudioEffect#getParameter(int[], short[]):
+
+BannedThrow: android.media.audiofx.AudioEffect#setParameter(byte[], byte[]):
+
+BannedThrow: android.media.audiofx.AudioEffect#setParameter(int, byte[]):
+
+BannedThrow: android.media.audiofx.AudioEffect#setParameter(int, int):
+
+BannedThrow: android.media.audiofx.AudioEffect#setParameter(int, short):
+
+BannedThrow: android.media.audiofx.AudioEffect#setParameter(int[], byte[]):
+
+BannedThrow: android.media.audiofx.AudioEffect#setParameter(int[], int[]):
+
+BannedThrow: android.media.audiopolicy.AudioMix.Builder#Builder(android.media.audiopolicy.AudioMixingRule):
+
+BannedThrow: android.media.audiopolicy.AudioMix.Builder#build():
+
+BannedThrow: android.media.audiopolicy.AudioMix.Builder#setDevice(android.media.AudioDeviceInfo):
+
+BannedThrow: android.media.audiopolicy.AudioMix.Builder#setFormat(android.media.AudioFormat):
+
+BannedThrow: android.media.audiopolicy.AudioMix.Builder#setRouteFlags(int):
+
+BannedThrow: android.media.audiopolicy.AudioMixingRule.Builder#addMixRule(int, Object):
+
+BannedThrow: android.media.audiopolicy.AudioMixingRule.Builder#addRule(android.media.AudioAttributes, int):
+
+BannedThrow: android.media.audiopolicy.AudioMixingRule.Builder#excludeMixRule(int, Object):
+
+BannedThrow: android.media.audiopolicy.AudioMixingRule.Builder#excludeRule(android.media.AudioAttributes, int):
+
+BannedThrow: android.media.audiopolicy.AudioPolicy#createAudioRecordSink(android.media.audiopolicy.AudioMix):
+
+BannedThrow: android.media.audiopolicy.AudioPolicy#createAudioTrackSource(android.media.audiopolicy.AudioMix):
+
+BannedThrow: android.media.audiopolicy.AudioPolicy#setFocusDuckingBehavior(int):
+
+BannedThrow: android.media.audiopolicy.AudioPolicy.Builder#addMix(android.media.audiopolicy.AudioMix):
+
+BannedThrow: android.media.audiopolicy.AudioPolicy.Builder#setLooper(android.os.Looper):
+
+BannedThrow: android.os.HwBinder#getService(String, String):
+
+BannedThrow: android.os.HwBinder#getService(String, String, boolean):
+
+BannedThrow: android.os.Process#getThreadScheduler(int):
+
+
+
+CallbackInterface: android.app.prediction.AppPredictor.Callback:
+
+CallbackInterface: android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback:
+
+CallbackInterface: android.widget.Magnifier.Callback:
+
+
+
+CallbackMethodName: android.os.RemoteCallback:
+
+
+
+ConcreteCollection: android.content.AutofillOptions#disabledActivities:
+
+ConcreteCollection: android.content.AutofillOptions#whitelistedActivitiesForAugmentedAutofill:
+
+ConcreteCollection: android.content.ContentCaptureOptions#ContentCaptureOptions(int, int, int, int, int, android.util.ArraySet<android.content.ComponentName>) parameter #5:
+
+ConcreteCollection: android.content.ContentCaptureOptions#whitelistedComponents:
+
+ConcreteCollection: android.database.sqlite.SQLiteDebug.PagerStats#dbStats:
+
+ConcreteCollection: android.os.HwParcel#readBoolVector():
+
+ConcreteCollection: android.os.HwParcel#readDoubleVector():
+
+ConcreteCollection: android.os.HwParcel#readFloatVector():
+
+ConcreteCollection: android.os.HwParcel#readInt16Vector():
+
+ConcreteCollection: android.os.HwParcel#readInt32Vector():
+
+ConcreteCollection: android.os.HwParcel#readInt64Vector():
+
+ConcreteCollection: android.os.HwParcel#readInt8Vector():
+
+ConcreteCollection: android.os.HwParcel#readNativeHandleVector():
+
+ConcreteCollection: android.os.HwParcel#readStringVector():
+
+ConcreteCollection: android.os.HwParcel#writeBoolVector(java.util.ArrayList<java.lang.Boolean>) parameter #0:
+
+ConcreteCollection: android.os.HwParcel#writeDoubleVector(java.util.ArrayList<java.lang.Double>) parameter #0:
+
+ConcreteCollection: android.os.HwParcel#writeFloatVector(java.util.ArrayList<java.lang.Float>) parameter #0:
+
+ConcreteCollection: android.os.HwParcel#writeInt16Vector(java.util.ArrayList<java.lang.Short>) parameter #0:
+
+ConcreteCollection: android.os.HwParcel#writeInt32Vector(java.util.ArrayList<java.lang.Integer>) parameter #0:
+
+ConcreteCollection: android.os.HwParcel#writeInt64Vector(java.util.ArrayList<java.lang.Long>) parameter #0:
+
+ConcreteCollection: android.os.HwParcel#writeInt8Vector(java.util.ArrayList<java.lang.Byte>) parameter #0:
+
+ConcreteCollection: android.os.HwParcel#writeNativeHandleVector(java.util.ArrayList<android.os.NativeHandle>) parameter #0:
+
+ConcreteCollection: android.os.HwParcel#writeStringVector(java.util.ArrayList<java.lang.String>) parameter #0:
+
+ConcreteCollection: android.service.autofill.CompositeUserData#getFieldClassificationAlgorithms():
+
+ConcreteCollection: android.service.autofill.CompositeUserData#getFieldClassificationArgs():
+
+ConcreteCollection: android.service.autofill.InternalTransformation#batchApply(android.service.autofill.ValueFinder, android.widget.RemoteViews, java.util.ArrayList<android.util.Pair<java.lang.Integer,android.service.autofill.InternalTransformation>>) parameter #2:
+
+ConcreteCollection: android.service.autofill.UserData#getFieldClassificationAlgorithms():
+
+ConcreteCollection: android.telephony.ims.ImsConferenceState#mParticipants:
+ Field type is concrete collection (`java.util.HashMap`); must be higher-level interface
+
+
+ContextFirst: android.os.VibrationEffect#get(android.net.Uri, android.content.Context) parameter #1:
+
+
+
+ContextNameSuffix: android.telephony.mbms.vendor.MbmsGroupCallServiceBase:
+
+
+
+EndsWithImpl: android.view.contentcapture.ViewNode.ViewStructureImpl:
+
+
+
+Enum: android.view.inspector.InspectableProperty.ValueType:
+
+
+
+EqualsAndHashCode: android.app.prediction.AppPredictionContext#equals(Object):
+
+EqualsAndHashCode: android.app.prediction.AppTarget#equals(Object):
+
+EqualsAndHashCode: android.app.prediction.AppTargetEvent#equals(Object):
+
+EqualsAndHashCode: android.net.apf.ApfCapabilities#equals(Object):
+
+EqualsAndHashCode: android.net.metrics.ApfProgramEvent#equals(Object):
+
+EqualsAndHashCode: android.net.metrics.ApfStats#equals(Object):
+
+EqualsAndHashCode: android.net.metrics.DhcpClientEvent#equals(Object):
+
+EqualsAndHashCode: android.net.metrics.IpManagerEvent#equals(Object):
+
+EqualsAndHashCode: android.net.metrics.IpReachabilityEvent#equals(Object):
+
+EqualsAndHashCode: android.net.metrics.NetworkEvent#equals(Object):
+
+EqualsAndHashCode: android.net.metrics.RaEvent#equals(Object):
+
+EqualsAndHashCode: android.net.metrics.ValidationProbeEvent#equals(Object):
+
+EqualsAndHashCode: android.os.IncidentManager.PendingReport#equals(Object):
+
+EqualsAndHashCode: android.os.StrictMode.ViolationInfo#hashCode():
+
+
+
+ExecutorRegistration: android.content.pm.PackageManager#addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener):
+
+ExecutorRegistration: android.hardware.camera2.CameraDevice#createCustomCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, int, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler):
+
+ExecutorRegistration: android.media.audiofx.AudioEffect#setParameterListener(android.media.audiofx.AudioEffect.OnParameterChangeListener):
+
+ExecutorRegistration: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener):
+
+ExecutorRegistration: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener):
+
+ExecutorRegistration: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyVolumeCallback(android.media.audiopolicy.AudioPolicy.AudioPolicyVolumeCallback):
+
+ExecutorRegistration: android.os.IncidentManager#cancelAuthorization(android.os.IncidentManager.AuthListener):
+
+ExecutorRegistration: android.os.IncidentManager#requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener):
+
+ExecutorRegistration: android.os.RemoteCallback#RemoteCallback(android.os.RemoteCallback.OnResultListener, android.os.Handler):
+
+ExecutorRegistration: android.permission.PermissionControllerManager#getAppPermissions(String, android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, android.os.Handler):
+
+ExecutorRegistration: android.telephony.ims.stub.ImsCallSessionImplBase#setListener(android.telephony.ims.ImsCallSessionListener):
+ Registration methods should have overload that accepts delivery Executor: `setListener`
+ExecutorRegistration: android.telephony.ims.stub.ImsUtImplBase#setListener(android.telephony.ims.ImsUtListener):
+ Registration methods should have overload that accepts delivery Executor: `setListener`
+ExecutorRegistration: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener):
+
+ExecutorRegistration: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener):
+
+ExecutorRegistration: android.telephony.mbms.vendor.MbmsDownloadServiceBase#initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback):
+
+ExecutorRegistration: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int):
+
+ExecutorRegistration: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#startGroupCall(int, long, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>, android.telephony.mbms.GroupCallCallback):
+
+ExecutorRegistration: android.telephony.mbms.vendor.MbmsStreamingServiceBase#initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int):
+
+ExecutorRegistration: android.telephony.mbms.vendor.MbmsStreamingServiceBase#startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback):
+
+
+
+ForbiddenSuperClass: android.app.AppDetailsActivity:
+
+
+
+GenericException: android.app.ActivityView#finalize():
+
+GenericException: android.app.prediction.AppPredictor#finalize():
+
+GenericException: android.service.autofill.CharSequenceTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int):
+
+GenericException: android.service.autofill.DateTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int):
+
+GenericException: android.service.autofill.ImageTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int):
+
+GenericException: android.service.autofill.augmented.FillWindow#finalize():
+
+
+
+GetterSetterNames: android.app.NotificationChannel#isBlockableSystem():
+
+GetterSetterNames: android.app.NotificationChannel#isImportanceLockedByCriticalDeviceFunction():
+
+GetterSetterNames: android.app.NotificationChannel#isImportanceLockedByOEM():
+
+GetterSetterNames: android.location.GnssClock#setBiasNanos(double):
+
+GetterSetterNames: android.location.GnssClock#setBiasUncertaintyNanos(double):
+
+GetterSetterNames: android.location.GnssClock#setDriftNanosPerSecond(double):
+
+GetterSetterNames: android.location.GnssClock#setDriftUncertaintyNanosPerSecond(double):
+
+GetterSetterNames: android.location.GnssClock#setElapsedRealtimeNanos(long):
+
+GetterSetterNames: android.location.GnssClock#setElapsedRealtimeUncertaintyNanos(double):
+
+GetterSetterNames: android.location.GnssClock#setFullBiasNanos(long):
+
+GetterSetterNames: android.location.GnssClock#setLeapSecond(int):
+
+GetterSetterNames: android.location.GnssClock#setTimeUncertaintyNanos(double):
+
+GetterSetterNames: android.location.GnssMeasurement#setCarrierFrequencyHz(float):
+
+GetterSetterNames: android.location.GnssMeasurement#setCodeType(String):
+
+GetterSetterNames: android.location.GnssMeasurement#setSnrInDb(double):
+
+GetterSetterNames: android.location.LocationRequest#isLocationSettingsIgnored():
+
+GetterSetterNames: android.location.LocationRequest#isLowPowerMode():
+
+GetterSetterNames: android.os.IncidentReportArgs#isAll():
+
+GetterSetterNames: android.service.notification.NotificationStats#setDirectReplied():
+
+GetterSetterNames: android.service.notification.NotificationStats#setExpanded():
+
+GetterSetterNames: android.service.notification.NotificationStats#setSeen():
+
+GetterSetterNames: android.service.notification.NotificationStats#setSnoozed():
+
+GetterSetterNames: android.service.notification.NotificationStats#setViewedSettings():
+
+GetterSetterNames: android.view.View#isAutofilled():
+
+GetterSetterNames: android.view.View#isDefaultFocusHighlightEnabled():
+
+
+
+IllegalStateException: android.media.audiopolicy.AudioMix.Builder#build():
+
+
+
+IntentBuilderName: android.app.backup.BackupManager#getConfigurationIntent(String):
+
+IntentBuilderName: android.app.backup.BackupManager#getDataManagementIntent(String):
+
+
+
+IntentName: android.provider.Settings.Secure#VOICE_INTERACTION_SERVICE:
+
+IntentName: android.provider.Telephony.Sms.Intents#SMS_CARRIER_PROVISION_ACTION:
+
+IntentName: android.service.notification.Adjustment#KEY_CONTEXTUAL_ACTIONS:
+
+
+
+InterfaceConstant: android.service.autofill.AutofillFieldClassificationService#SERVICE_INTERFACE:
+
+InterfaceConstant: android.service.autofill.augmented.AugmentedAutofillService#SERVICE_INTERFACE:
+
+InterfaceConstant: android.service.contentcapture.ContentCaptureService#SERVICE_INTERFACE:
+
+InterfaceConstant: android.service.notification.NotificationAssistantService#SERVICE_INTERFACE:
+
+InterfaceConstant: android.telecom.PhoneAccountSuggestionService#SERVICE_INTERFACE:
+
+
+
+InternalField: android.telephony.ims.ImsConferenceState#mParticipants:
+ Internal field mParticipants must not be exposed
+
+
+KotlinOperator: android.os.WorkSource#get(int):
+
+
+
+ListenerInterface: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener:
+
+ListenerInterface: android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener:
+
+ListenerInterface: android.os.IncidentManager.AuthListener:
+
+ListenerInterface: android.telephony.ims.ImsCallSessionListener:
+ Listeners should be an interface, or otherwise renamed Callback: ImsCallSessionListener
+ListenerInterface: android.telephony.ims.ImsUtListener:
+ Listeners should be an interface, or otherwise renamed Callback: ImsUtListener
+
+
+ListenerLast: android.hardware.camera2.CameraDevice#createCustomCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, int, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) parameter #4:
+
+ListenerLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper) parameter #2:
+
+ListenerLast: android.permission.PermissionControllerManager#getAppPermissions(String, android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, android.os.Handler) parameter #2:
+
+ListenerLast: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int) parameter #1:
+
+ListenerLast: android.telephony.mbms.vendor.MbmsStreamingServiceBase#initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int) parameter #1:
+
+
+
+ManagerConstructor: android.content.pm.ShortcutManager#ShortcutManager(android.content.Context):
+
+
+
+ManagerLookup: android.telephony.ims.ImsMmTelManager#createForSubscriptionId(int):
+ Managers must always be obtained from Context (`createForSubscriptionId`)
+ManagerLookup: android.telephony.ims.ProvisioningManager#createForSubscriptionId(int):
+ Managers must always be obtained from Context (`createForSubscriptionId`)
+
+
+MethodNameTense: android.telephony.ims.feature.CapabilityChangeRequest#getCapabilitiesToEnable():
+ Unexpected tense; probably meant `enabled`, was `getCapabilitiesToEnable`
+
+
+MethodNameUnits: android.telephony.ims.ImsCallForwardInfo#getTimeSeconds():
+ Returned time values must be in milliseconds, was `getTimeSeconds`
+
+
+MinMaxConstant: android.os.UserHandle#MIN_SECONDARY_USER_ID:
+
+MinMaxConstant: android.view.autofill.AutofillManager#MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS:
+
+
+
+MissingNullability: android.app.Activity#onMovedToDisplay(int, android.content.res.Configuration) parameter #1:
+
+MissingNullability: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int) parameter #0:
+
+MissingNullability: android.app.ActivityManager#alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName) parameter #0:
+
+MissingNullability: android.app.ActivityManager#forceStopPackage(String) parameter #0:
+
+MissingNullability: android.app.ActivityManager#getPackageImportance(String) parameter #0:
+
+MissingNullability: android.app.ActivityManager#removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener) parameter #0:
+
+MissingNullability: android.app.ActivityManager#scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int) parameter #0:
+
+MissingNullability: android.app.ActivityManager.TaskDescription#getIconFilename():
+
+MissingNullability: android.app.ActivityTaskManager#clearLaunchParamsForPackages(java.util.List<java.lang.String>) parameter #0:
+
+MissingNullability: android.app.ActivityTaskManager#listAllStacks():
+
+MissingNullability: android.app.ActivityTaskManager#moveTopActivityToPinnedStack(int, android.graphics.Rect) parameter #1:
+
+MissingNullability: android.app.ActivityTaskManager#removeStacksInWindowingModes(int[]) parameter #0:
+
+MissingNullability: android.app.ActivityTaskManager#removeStacksWithActivityTypes(int[]) parameter #0:
+
+MissingNullability: android.app.ActivityTaskManager#resizeDockedStack(android.graphics.Rect, android.graphics.Rect) parameter #0:
+
+MissingNullability: android.app.ActivityTaskManager#resizeDockedStack(android.graphics.Rect, android.graphics.Rect) parameter #1:
+
+MissingNullability: android.app.ActivityTaskManager#resizePinnedStack(int, android.graphics.Rect, boolean) parameter #1:
+
+MissingNullability: android.app.ActivityTaskManager#resizeTask(int, android.graphics.Rect) parameter #1:
+
+MissingNullability: android.app.ActivityTaskManager#setTaskWindowingModeSplitScreenPrimary(int, int, boolean, boolean, android.graphics.Rect, boolean) parameter #4:
+
+MissingNullability: android.app.ActivityTaskManager#supportsMultiWindow(android.content.Context) parameter #0:
+
+MissingNullability: android.app.ActivityTaskManager#supportsSplitScreenMultiWindow(android.content.Context) parameter #0:
+
+MissingNullability: android.app.ActivityView#ActivityView(android.content.Context) parameter #0:
+
+MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet) parameter #0:
+
+MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet) parameter #1:
+
+MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet, int) parameter #0:
+
+MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet, int) parameter #1:
+
+MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet, int, boolean) parameter #0:
+
+MissingNullability: android.app.ActivityView#ActivityView(android.content.Context, android.util.AttributeSet, int, boolean) parameter #1:
+
+MissingNullability: android.app.ActivityView#gatherTransparentRegion(android.graphics.Region) parameter #0:
+
+MissingNullability: android.app.ActivityView#onVisibilityChanged(android.view.View, int) parameter #0:
+
+MissingNullability: android.app.ActivityView#setCallback(android.app.ActivityView.StateCallback) parameter #0:
+
+MissingNullability: android.app.ActivityView#setForwardedInsets(android.graphics.Insets) parameter #0:
+
+MissingNullability: android.app.ActivityView#startActivity(android.content.Intent, android.os.UserHandle) parameter #1:
+
+MissingNullability: android.app.ActivityView.StateCallback#onActivityViewDestroyed(android.app.ActivityView) parameter #0:
+
+MissingNullability: android.app.ActivityView.StateCallback#onActivityViewReady(android.app.ActivityView) parameter #0:
+
+MissingNullability: android.app.ActivityView.StateCallback#onTaskCreated(int, android.content.ComponentName) parameter #1:
+
+MissingNullability: android.app.AppDetailsActivity#onCreate(android.os.Bundle) parameter #0:
+
+MissingNullability: android.app.AppOpsManager#getOpStrs():
+
+MissingNullability: android.app.AppOpsManager#isOperationActive(int, int, String) parameter #2:
+
+MissingNullability: android.app.AppOpsManager#opToPermission(int):
+
+MissingNullability: android.app.AppOpsManager#permissionToOpCode(String) parameter #0:
+
+MissingNullability: android.app.AppOpsManager#setMode(String, int, String, int) parameter #0:
+
+MissingNullability: android.app.AppOpsManager#setMode(String, int, String, int) parameter #2:
+
+MissingNullability: android.app.AppOpsManager#setMode(int, int, String, int) parameter #2:
+
+MissingNullability: android.app.AppOpsManager#setUidMode(String, int, int) parameter #0:
+
+MissingNullability: android.app.AppOpsManager.HistoricalOp#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.app.AppOpsManager.HistoricalOps#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.app.AppOpsManager.HistoricalUidOps#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.app.AppOpsManager.OpEntry#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.app.NotificationManager#allowAssistantAdjustment(String) parameter #0:
+
+MissingNullability: android.app.NotificationManager#disallowAssistantAdjustment(String) parameter #0:
+
+MissingNullability: android.app.NotificationManager#getEffectsSuppressor():
+
+MissingNullability: android.app.NotificationManager#matchesCallFilter(android.os.Bundle) parameter #0:
+
+MissingNullability: android.app.PictureInPictureParams#getActions():
+
+MissingNullability: android.app.PictureInPictureParams#getSourceRectHint():
+
+MissingNullability: android.app.TimePickerDialog#getTimePicker():
+
+MissingNullability: android.app.UiAutomation#executeShellCommandRw(String):
+
+MissingNullability: android.app.UiAutomation#executeShellCommandRw(String) parameter #0:
+
+MissingNullability: android.app.UiAutomation#grantRuntimePermission(String, String, android.os.UserHandle) parameter #0:
+
+MissingNullability: android.app.UiAutomation#grantRuntimePermission(String, String, android.os.UserHandle) parameter #1:
+
+MissingNullability: android.app.UiAutomation#grantRuntimePermission(String, String, android.os.UserHandle) parameter #2:
+
+MissingNullability: android.app.UiAutomation#revokeRuntimePermission(String, String, android.os.UserHandle) parameter #0:
+
+MissingNullability: android.app.UiAutomation#revokeRuntimePermission(String, String, android.os.UserHandle) parameter #1:
+
+MissingNullability: android.app.UiAutomation#revokeRuntimePermission(String, String, android.os.UserHandle) parameter #2:
+
+MissingNullability: android.app.WallpaperManager#setWallpaperComponent(android.content.ComponentName) parameter #0:
+
+MissingNullability: android.app.WindowConfiguration#compareTo(android.app.WindowConfiguration) parameter #0:
+
+MissingNullability: android.app.WindowConfiguration#getAppBounds():
+
+MissingNullability: android.app.WindowConfiguration#getBounds():
+
+MissingNullability: android.app.WindowConfiguration#setAppBounds(android.graphics.Rect) parameter #0:
+
+MissingNullability: android.app.WindowConfiguration#setBounds(android.graphics.Rect) parameter #0:
+
+MissingNullability: android.app.WindowConfiguration#setTo(android.app.WindowConfiguration) parameter #0:
+
+MissingNullability: android.app.WindowConfiguration#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.app.admin.DevicePolicyManager#getOwnerInstalledCaCerts(android.os.UserHandle):
+
+MissingNullability: android.app.admin.SecurityLog.SecurityEvent#SecurityEvent(long, byte[]) parameter #1:
+
+MissingNullability: android.app.backup.BackupManager#getConfigurationIntent(String):
+
+MissingNullability: android.app.backup.BackupManager#getConfigurationIntent(String) parameter #0:
+
+MissingNullability: android.app.backup.BackupManager#getDataManagementIntent(String):
+
+MissingNullability: android.app.backup.BackupManager#getDataManagementIntent(String) parameter #0:
+
+MissingNullability: android.app.backup.BackupManager#getDestinationString(String):
+
+MissingNullability: android.app.backup.BackupManager#getDestinationString(String) parameter #0:
+
+MissingNullability: android.app.prediction.AppPredictionSessionId#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.app.prediction.AppPredictor#getSessionId():
+
+MissingNullability: android.app.prediction.AppTarget#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.app.prediction.AppTargetEvent#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.app.prediction.AppTargetId#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.content.AutofillOptions#forWhitelistingItself():
+
+MissingNullability: android.content.AutofillOptions#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.content.ContentCaptureOptions#forWhitelistingItself():
+
+MissingNullability: android.content.ContentCaptureOptions#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.content.ContentResolver#getSyncAdapterPackagesForAuthorityAsUser(String, int):
+
+MissingNullability: android.content.ContentResolver#getSyncAdapterPackagesForAuthorityAsUser(String, int) parameter #0:
+
+MissingNullability: android.content.Context#getDisplay():
+
+MissingNullability: android.content.Context#getUser():
+
+MissingNullability: android.content.ContextWrapper#getDisplay():
+
+MissingNullability: android.content.ContextWrapper#setContentCaptureOptions(android.content.ContentCaptureOptions) parameter #0:
+
+MissingNullability: android.content.pm.ActivityInfo#isTranslucentOrFloating(android.content.res.TypedArray) parameter #0:
+
+MissingNullability: android.content.pm.LauncherApps#LauncherApps(android.content.Context) parameter #0:
+
+MissingNullability: android.content.pm.PackageInstaller.SessionParams#setGrantedRuntimePermissions(String[]) parameter #0:
+
+MissingNullability: android.content.pm.PackageManager#getNamesForUids(int[]) parameter #0:
+
+MissingNullability: android.content.pm.ShortcutManager#ShortcutManager(android.content.Context) parameter #0:
+
+MissingNullability: android.content.res.AssetManager#getOverlayablesToString(String) parameter #0:
+
+MissingNullability: android.content.res.Configuration#windowConfiguration:
+
+MissingNullability: android.content.rollback.PackageRollbackInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.content.rollback.RollbackInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.database.sqlite.SQLiteDebug#dump(android.util.Printer, String[]) parameter #0:
+
+MissingNullability: android.database.sqlite.SQLiteDebug#dump(android.util.Printer, String[]) parameter #1:
+
+MissingNullability: android.database.sqlite.SQLiteDebug#getDatabaseInfo():
+
+MissingNullability: android.database.sqlite.SQLiteDebug.DbStats#DbStats(String, long, long, int, int, int, int) parameter #0:
+
+MissingNullability: android.database.sqlite.SQLiteDebug.DbStats#cache:
+
+MissingNullability: android.database.sqlite.SQLiteDebug.DbStats#dbName:
+
+MissingNullability: android.database.sqlite.SQLiteDebug.PagerStats#dbStats:
+
+MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#SQLiteDirectCursorDriver(android.database.sqlite.SQLiteDatabase, String, String, android.os.CancellationSignal) parameter #0:
+
+MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#SQLiteDirectCursorDriver(android.database.sqlite.SQLiteDatabase, String, String, android.os.CancellationSignal) parameter #1:
+
+MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#SQLiteDirectCursorDriver(android.database.sqlite.SQLiteDatabase, String, String, android.os.CancellationSignal) parameter #2:
+
+MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#SQLiteDirectCursorDriver(android.database.sqlite.SQLiteDatabase, String, String, android.os.CancellationSignal) parameter #3:
+
+MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#cursorRequeried(android.database.Cursor) parameter #0:
+
+MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#query(android.database.sqlite.SQLiteDatabase.CursorFactory, String[]):
+
+MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#query(android.database.sqlite.SQLiteDatabase.CursorFactory, String[]) parameter #0:
+
+MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#query(android.database.sqlite.SQLiteDatabase.CursorFactory, String[]) parameter #1:
+
+MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#setBindArguments(String[]) parameter #0:
+
+MissingNullability: android.database.sqlite.SQLiteGlobal#getDefaultJournalMode():
+
+MissingNullability: android.database.sqlite.SQLiteGlobal#getDefaultSyncMode():
+
+MissingNullability: android.database.sqlite.SQLiteGlobal#getWALSyncMode():
+
+MissingNullability: android.graphics.ImageDecoder#createSource(android.content.res.Resources, java.io.InputStream, int) parameter #0:
+
+MissingNullability: android.graphics.ImageDecoder#createSource(android.content.res.Resources, java.io.InputStream, int) parameter #1:
+
+MissingNullability: android.graphics.drawable.AdaptiveIconDrawable#getSafeZone():
+
+MissingNullability: android.graphics.drawable.ColorDrawable#getXfermode():
+
+MissingNullability: android.hardware.camera2.CameraDevice#createCustomCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, int, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) parameter #0:
+
+MissingNullability: android.hardware.camera2.CameraManager#getCameraIdListNoLazy():
+
+MissingNullability: android.hardware.display.AmbientBrightnessDayStats#getBucketBoundaries():
+
+MissingNullability: android.hardware.display.AmbientBrightnessDayStats#getLocalDate():
+
+MissingNullability: android.hardware.display.AmbientBrightnessDayStats#getStats():
+
+MissingNullability: android.hardware.display.AmbientBrightnessDayStats#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.hardware.display.AmbientDisplayConfiguration#AmbientDisplayConfiguration(android.content.Context) parameter #0:
+
+MissingNullability: android.hardware.display.BrightnessChangeEvent#luxTimestamps:
+
+MissingNullability: android.hardware.display.BrightnessChangeEvent#luxValues:
+
+MissingNullability: android.hardware.display.BrightnessChangeEvent#packageName:
+
+MissingNullability: android.hardware.display.BrightnessChangeEvent#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.hardware.display.BrightnessConfiguration#getCurve():
+
+MissingNullability: android.hardware.display.BrightnessConfiguration#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.hardware.display.BrightnessConfiguration.Builder#Builder(float[], float[]) parameter #0:
+
+MissingNullability: android.hardware.display.BrightnessConfiguration.Builder#Builder(float[], float[]) parameter #1:
+
+MissingNullability: android.hardware.display.BrightnessCorrection#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.hardware.display.DisplayManager#getAmbientBrightnessStats():
+
+MissingNullability: android.hardware.display.DisplayManager#getBrightnessConfiguration():
+
+MissingNullability: android.hardware.display.DisplayManager#getBrightnessEvents():
+
+MissingNullability: android.hardware.display.DisplayManager#getStableDisplaySize():
+
+MissingNullability: android.hardware.display.DisplayManager#setBrightnessConfiguration(android.hardware.display.BrightnessConfiguration) parameter #0:
+
+MissingNullability: android.location.GnssClock#set(android.location.GnssClock) parameter #0:
+
+MissingNullability: android.location.GnssMeasurement#set(android.location.GnssMeasurement) parameter #0:
+
+MissingNullability: android.location.GnssMeasurementsEvent#GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]) parameter #0:
+
+MissingNullability: android.location.GnssMeasurementsEvent#GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]) parameter #1:
+
+MissingNullability: android.location.GnssNavigationMessage#set(android.location.GnssNavigationMessage) parameter #0:
+
+MissingNullability: android.location.GnssNavigationMessage#setData(byte[]) parameter #0:
+
+MissingNullability: android.location.LocationManager#getTestProviderCurrentRequests(String) parameter #0:
+
+MissingNullability: android.location.LocationRequest#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.media.AudioFocusInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String) parameter #3:
+
+MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String) parameter #4:
+
+MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String) parameter #6:
+
+MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #10:
+
+MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #11:
+
+MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #3:
+
+MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #4:
+
+MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #6:
+
+MissingNullability: android.media.PlaybackParams#setAudioStretchMode(int):
+
+MissingNullability: android.media.audiofx.AudioEffect#EFFECT_TYPE_NULL:
+
+MissingNullability: android.media.audiofx.AudioEffect#byteArrayToInt(byte[]) parameter #0:
+
+MissingNullability: android.media.audiofx.AudioEffect#byteArrayToShort(byte[]) parameter #0:
+
+MissingNullability: android.media.audiofx.AudioEffect#getParameter(byte[], byte[]) parameter #0:
+
+MissingNullability: android.media.audiofx.AudioEffect#getParameter(byte[], byte[]) parameter #1:
+
+MissingNullability: android.media.audiofx.AudioEffect#getParameter(int, byte[]) parameter #1:
+
+MissingNullability: android.media.audiofx.AudioEffect#getParameter(int, int[]) parameter #1:
+
+MissingNullability: android.media.audiofx.AudioEffect#getParameter(int, short[]) parameter #1:
+
+MissingNullability: android.media.audiofx.AudioEffect#getParameter(int[], short[]) parameter #0:
+
+MissingNullability: android.media.audiofx.AudioEffect#getParameter(int[], short[]) parameter #1:
+
+MissingNullability: android.media.audiofx.AudioEffect#intToByteArray(int):
+
+MissingNullability: android.media.audiofx.AudioEffect#isEffectTypeAvailable(java.util.UUID) parameter #0:
+
+MissingNullability: android.media.audiofx.AudioEffect#setParameter(byte[], byte[]) parameter #0:
+
+MissingNullability: android.media.audiofx.AudioEffect#setParameter(byte[], byte[]) parameter #1:
+
+MissingNullability: android.media.audiofx.AudioEffect#setParameter(int, byte[]) parameter #1:
+
+MissingNullability: android.media.audiofx.AudioEffect#setParameter(int[], byte[]) parameter #0:
+
+MissingNullability: android.media.audiofx.AudioEffect#setParameter(int[], byte[]) parameter #1:
+
+MissingNullability: android.media.audiofx.AudioEffect#setParameter(int[], int[]) parameter #0:
+
+MissingNullability: android.media.audiofx.AudioEffect#setParameter(int[], int[]) parameter #1:
+
+MissingNullability: android.media.audiofx.AudioEffect#setParameterListener(android.media.audiofx.AudioEffect.OnParameterChangeListener) parameter #0:
+
+MissingNullability: android.media.audiofx.AudioEffect#shortToByteArray(short):
+
+MissingNullability: android.media.audiofx.AudioEffect.Descriptor#Descriptor(android.os.Parcel) parameter #0:
+
+MissingNullability: android.media.audiofx.AudioEffect.Descriptor#writeToParcel(android.os.Parcel) parameter #0:
+
+MissingNullability: android.media.audiofx.AudioEffect.OnParameterChangeListener#onParameterChange(android.media.audiofx.AudioEffect, int, byte[], byte[]) parameter #0:
+
+MissingNullability: android.media.audiofx.AudioEffect.OnParameterChangeListener#onParameterChange(android.media.audiofx.AudioEffect, int, byte[], byte[]) parameter #2:
+
+MissingNullability: android.media.audiofx.AudioEffect.OnParameterChangeListener#onParameterChange(android.media.audiofx.AudioEffect, int, byte[], byte[]) parameter #3:
+
+MissingNullability: android.media.audiopolicy.AudioMix.Builder#Builder(android.media.audiopolicy.AudioMixingRule) parameter #0:
+
+MissingNullability: android.media.audiopolicy.AudioMix.Builder#build():
+
+MissingNullability: android.media.audiopolicy.AudioMix.Builder#setDevice(android.media.AudioDeviceInfo):
+
+MissingNullability: android.media.audiopolicy.AudioMix.Builder#setFormat(android.media.AudioFormat):
+
+MissingNullability: android.media.audiopolicy.AudioMix.Builder#setFormat(android.media.AudioFormat) parameter #0:
+
+MissingNullability: android.media.audiopolicy.AudioMix.Builder#setRouteFlags(int):
+
+MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#addMixRule(int, Object):
+
+MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#addMixRule(int, Object) parameter #1:
+
+MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#addRule(android.media.AudioAttributes, int):
+
+MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#addRule(android.media.AudioAttributes, int) parameter #0:
+
+MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#build():
+
+MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#excludeMixRule(int, Object):
+
+MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#excludeMixRule(int, Object) parameter #1:
+
+MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#excludeRule(android.media.AudioAttributes, int):
+
+MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#excludeRule(android.media.AudioAttributes, int) parameter #0:
+
+MissingNullability: android.media.audiopolicy.AudioPolicy#createAudioRecordSink(android.media.audiopolicy.AudioMix):
+
+MissingNullability: android.media.audiopolicy.AudioPolicy#createAudioRecordSink(android.media.audiopolicy.AudioMix) parameter #0:
+
+MissingNullability: android.media.audiopolicy.AudioPolicy#createAudioTrackSource(android.media.audiopolicy.AudioMix):
+
+MissingNullability: android.media.audiopolicy.AudioPolicy#createAudioTrackSource(android.media.audiopolicy.AudioMix) parameter #0:
+
+MissingNullability: android.media.audiopolicy.AudioPolicy#setRegistration(String) parameter #0:
+
+MissingNullability: android.media.audiopolicy.AudioPolicy#toLogFriendlyString():
+
+MissingNullability: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener#onAudioFocusAbandon(android.media.AudioFocusInfo) parameter #0:
+
+MissingNullability: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener#onAudioFocusGrant(android.media.AudioFocusInfo, int) parameter #0:
+
+MissingNullability: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener#onAudioFocusLoss(android.media.AudioFocusInfo, boolean) parameter #0:
+
+MissingNullability: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener#onAudioFocusRequest(android.media.AudioFocusInfo, int) parameter #0:
+
+MissingNullability: android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener#onMixStateUpdate(android.media.audiopolicy.AudioMix) parameter #0:
+
+MissingNullability: android.media.audiopolicy.AudioPolicy.Builder#Builder(android.content.Context) parameter #0:
+
+MissingNullability: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener) parameter #0:
+
+MissingNullability: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener) parameter #0:
+
+MissingNullability: android.metrics.LogMaker#LogMaker(Object[]) parameter #0:
+
+MissingNullability: android.metrics.LogMaker#addTaggedData(int, Object):
+
+MissingNullability: android.metrics.LogMaker#addTaggedData(int, Object) parameter #1:
+
+MissingNullability: android.metrics.LogMaker#clearCategory():
+
+MissingNullability: android.metrics.LogMaker#clearPackageName():
+
+MissingNullability: android.metrics.LogMaker#clearSubtype():
+
+MissingNullability: android.metrics.LogMaker#clearTaggedData(int):
+
+MissingNullability: android.metrics.LogMaker#clearType():
+
+MissingNullability: android.metrics.LogMaker#deserialize(Object[]) parameter #0:
+
+MissingNullability: android.metrics.LogMaker#getCounterName():
+
+MissingNullability: android.metrics.LogMaker#getPackageName():
+
+MissingNullability: android.metrics.LogMaker#getTaggedData(int):
+
+MissingNullability: android.metrics.LogMaker#isSubsetOf(android.metrics.LogMaker) parameter #0:
+
+MissingNullability: android.metrics.LogMaker#isValidValue(Object) parameter #0:
+
+MissingNullability: android.metrics.LogMaker#serialize():
+
+MissingNullability: android.metrics.LogMaker#setCategory(int):
+
+MissingNullability: android.metrics.LogMaker#setPackageName(String):
+
+MissingNullability: android.metrics.LogMaker#setPackageName(String) parameter #0:
+
+MissingNullability: android.metrics.LogMaker#setSubtype(int):
+
+MissingNullability: android.metrics.LogMaker#setType(int):
+
+MissingNullability: android.metrics.MetricsReader#next():
+
+MissingNullability: android.net.NetworkCapabilities#getCapabilities():
+
+MissingNullability: android.net.StaticIpConfiguration#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.net.TestNetworkInterface#CREATOR:
+
+MissingNullability: android.net.TestNetworkInterface#TestNetworkInterface(android.os.ParcelFileDescriptor, String) parameter #0:
+
+MissingNullability: android.net.TestNetworkInterface#TestNetworkInterface(android.os.ParcelFileDescriptor, String) parameter #1:
+
+MissingNullability: android.net.TestNetworkInterface#getFileDescriptor():
+
+MissingNullability: android.net.TestNetworkInterface#getInterfaceName():
+
+MissingNullability: android.net.TestNetworkInterface#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.net.TestNetworkManager#createTapInterface():
+
+MissingNullability: android.net.TestNetworkManager#createTunInterface(android.net.LinkAddress[]):
+
+MissingNullability: android.net.apf.ApfCapabilities#CREATOR:
+
+MissingNullability: android.net.apf.ApfCapabilities#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.net.metrics.DhcpClientEvent.Builder#setMsg(String) parameter #0:
+
+MissingNullability: android.os.Build#is64BitAbi(String) parameter #0:
+
+MissingNullability: android.os.Build.VERSION#ACTIVE_CODENAMES:
+
+MissingNullability: android.os.Environment#buildPath(java.io.File, java.lang.String...):
+
+MissingNullability: android.os.Environment#buildPath(java.io.File, java.lang.String...) parameter #0:
+
+MissingNullability: android.os.Environment#buildPath(java.io.File, java.lang.String...) parameter #1:
+
+MissingNullability: android.os.FileUtils#contains(java.io.File, java.io.File) parameter #0:
+
+MissingNullability: android.os.FileUtils#contains(java.io.File, java.io.File) parameter #1:
+
+MissingNullability: android.os.HwBinder#getService(String, String):
+
+MissingNullability: android.os.HwBinder#getService(String, String) parameter #0:
+
+MissingNullability: android.os.HwBinder#getService(String, String) parameter #1:
+
+MissingNullability: android.os.HwBinder#getService(String, String, boolean):
+
+MissingNullability: android.os.HwBinder#getService(String, String, boolean) parameter #0:
+
+MissingNullability: android.os.HwBinder#getService(String, String, boolean) parameter #1:
+
+MissingNullability: android.os.HwBinder#onTransact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #1:
+
+MissingNullability: android.os.HwBinder#onTransact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #2:
+
+MissingNullability: android.os.HwBinder#registerService(String) parameter #0:
+
+MissingNullability: android.os.HwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #1:
+
+MissingNullability: android.os.HwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #2:
+
+MissingNullability: android.os.HwBlob#copyToBoolArray(long, boolean[], int) parameter #1:
+
+MissingNullability: android.os.HwBlob#copyToDoubleArray(long, double[], int) parameter #1:
+
+MissingNullability: android.os.HwBlob#copyToFloatArray(long, float[], int) parameter #1:
+
+MissingNullability: android.os.HwBlob#copyToInt16Array(long, short[], int) parameter #1:
+
+MissingNullability: android.os.HwBlob#copyToInt32Array(long, int[], int) parameter #1:
+
+MissingNullability: android.os.HwBlob#copyToInt64Array(long, long[], int) parameter #1:
+
+MissingNullability: android.os.HwBlob#copyToInt8Array(long, byte[], int) parameter #1:
+
+MissingNullability: android.os.HwBlob#getString(long):
+
+MissingNullability: android.os.HwBlob#putBlob(long, android.os.HwBlob) parameter #1:
+
+MissingNullability: android.os.HwBlob#putBoolArray(long, boolean[]) parameter #1:
+
+MissingNullability: android.os.HwBlob#putDoubleArray(long, double[]) parameter #1:
+
+MissingNullability: android.os.HwBlob#putFloatArray(long, float[]) parameter #1:
+
+MissingNullability: android.os.HwBlob#putInt16Array(long, short[]) parameter #1:
+
+MissingNullability: android.os.HwBlob#putInt32Array(long, int[]) parameter #1:
+
+MissingNullability: android.os.HwBlob#putInt64Array(long, long[]) parameter #1:
+
+MissingNullability: android.os.HwBlob#putInt8Array(long, byte[]) parameter #1:
+
+MissingNullability: android.os.HwBlob#putString(long, String) parameter #1:
+
+MissingNullability: android.os.HwBlob#wrapArray(boolean[]):
+
+MissingNullability: android.os.HwBlob#wrapArray(byte[]):
+
+MissingNullability: android.os.HwBlob#wrapArray(double[]):
+
+MissingNullability: android.os.HwBlob#wrapArray(float[]):
+
+MissingNullability: android.os.HwBlob#wrapArray(int[]):
+
+MissingNullability: android.os.HwBlob#wrapArray(long[]):
+
+MissingNullability: android.os.HwBlob#wrapArray(short[]):
+
+MissingNullability: android.os.HwParcel#enforceInterface(String) parameter #0:
+
+MissingNullability: android.os.HwParcel#readBoolVector():
+
+MissingNullability: android.os.HwParcel#readBuffer(long):
+
+MissingNullability: android.os.HwParcel#readDoubleVector():
+
+MissingNullability: android.os.HwParcel#readEmbeddedBuffer(long, long, long, boolean):
+
+MissingNullability: android.os.HwParcel#readFloatVector():
+
+MissingNullability: android.os.HwParcel#readInt16Vector():
+
+MissingNullability: android.os.HwParcel#readInt32Vector():
+
+MissingNullability: android.os.HwParcel#readInt64Vector():
+
+MissingNullability: android.os.HwParcel#readInt8Vector():
+
+MissingNullability: android.os.HwParcel#readString():
+
+MissingNullability: android.os.HwParcel#readStringVector():
+
+MissingNullability: android.os.HwParcel#readStrongBinder():
+
+MissingNullability: android.os.HwParcel#writeBoolVector(java.util.ArrayList<java.lang.Boolean>) parameter #0:
+
+MissingNullability: android.os.HwParcel#writeBuffer(android.os.HwBlob) parameter #0:
+
+MissingNullability: android.os.HwParcel#writeDoubleVector(java.util.ArrayList<java.lang.Double>) parameter #0:
+
+MissingNullability: android.os.HwParcel#writeFloatVector(java.util.ArrayList<java.lang.Float>) parameter #0:
+
+MissingNullability: android.os.HwParcel#writeInt16Vector(java.util.ArrayList<java.lang.Short>) parameter #0:
+
+MissingNullability: android.os.HwParcel#writeInt32Vector(java.util.ArrayList<java.lang.Integer>) parameter #0:
+
+MissingNullability: android.os.HwParcel#writeInt64Vector(java.util.ArrayList<java.lang.Long>) parameter #0:
+
+MissingNullability: android.os.HwParcel#writeInt8Vector(java.util.ArrayList<java.lang.Byte>) parameter #0:
+
+MissingNullability: android.os.HwParcel#writeInterfaceToken(String) parameter #0:
+
+MissingNullability: android.os.HwParcel#writeString(String) parameter #0:
+
+MissingNullability: android.os.HwParcel#writeStringVector(java.util.ArrayList<java.lang.String>) parameter #0:
+
+MissingNullability: android.os.HwParcel#writeStrongBinder(android.os.IHwBinder) parameter #0:
+
+MissingNullability: android.os.IHwBinder#linkToDeath(android.os.IHwBinder.DeathRecipient, long) parameter #0:
+
+MissingNullability: android.os.IHwBinder#queryLocalInterface(String):
+
+MissingNullability: android.os.IHwBinder#queryLocalInterface(String) parameter #0:
+
+MissingNullability: android.os.IHwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #1:
+
+MissingNullability: android.os.IHwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #2:
+
+MissingNullability: android.os.IHwBinder#unlinkToDeath(android.os.IHwBinder.DeathRecipient) parameter #0:
+
+MissingNullability: android.os.IHwInterface#asBinder():
+
+MissingNullability: android.os.IncidentManager#approveReport(android.net.Uri) parameter #0:
+
+MissingNullability: android.os.IncidentManager#cancelAuthorization(android.os.IncidentManager.AuthListener) parameter #0:
+
+MissingNullability: android.os.IncidentManager#deleteIncidentReports(android.net.Uri) parameter #0:
+
+MissingNullability: android.os.IncidentManager#denyReport(android.net.Uri) parameter #0:
+
+MissingNullability: android.os.IncidentManager#getIncidentReport(android.net.Uri) parameter #0:
+
+MissingNullability: android.os.IncidentManager#getIncidentReportList(String) parameter #0:
+
+MissingNullability: android.os.IncidentManager#getPendingReports():
+
+MissingNullability: android.os.IncidentManager#reportIncident(android.os.IncidentReportArgs) parameter #0:
+
+MissingNullability: android.os.IncidentManager#requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener) parameter #1:
+
+MissingNullability: android.os.IncidentManager#requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener) parameter #3:
+
+MissingNullability: android.os.IncidentManager.IncidentReport#IncidentReport(android.os.Parcel) parameter #0:
+
+MissingNullability: android.os.IncidentManager.IncidentReport#getInputStream():
+
+MissingNullability: android.os.IncidentManager.IncidentReport#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.os.IncidentReportArgs#IncidentReportArgs(android.os.Parcel) parameter #0:
+
+MissingNullability: android.os.IncidentReportArgs#addHeader(byte[]) parameter #0:
+
+MissingNullability: android.os.IncidentReportArgs#readFromParcel(android.os.Parcel) parameter #0:
+
+MissingNullability: android.os.IncidentReportArgs#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.os.ParcelFileDescriptor#getFile(java.io.FileDescriptor):
+
+MissingNullability: android.os.ParcelFileDescriptor#getFile(java.io.FileDescriptor) parameter #0:
+
+MissingNullability: android.os.RemoteCallback#RemoteCallback(android.os.RemoteCallback.OnResultListener) parameter #0:
+
+MissingNullability: android.os.RemoteCallback#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.os.StrictMode#setViolationLogger(android.os.StrictMode.ViolationLogger) parameter #0:
+
+MissingNullability: android.os.StrictMode.ViolationInfo#ViolationInfo(android.os.Parcel) parameter #0:
+
+MissingNullability: android.os.StrictMode.ViolationInfo#ViolationInfo(android.os.Parcel, boolean) parameter #0:
+
+MissingNullability: android.os.StrictMode.ViolationInfo#broadcastIntentAction:
+
+MissingNullability: android.os.StrictMode.ViolationInfo#dump(android.util.Printer, String) parameter #0:
+
+MissingNullability: android.os.StrictMode.ViolationInfo#dump(android.util.Printer, String) parameter #1:
+
+MissingNullability: android.os.StrictMode.ViolationInfo#getStackTrace():
+
+MissingNullability: android.os.StrictMode.ViolationInfo#getViolationClass():
+
+MissingNullability: android.os.StrictMode.ViolationInfo#getViolationDetails():
+
+MissingNullability: android.os.StrictMode.ViolationInfo#tags:
+
+MissingNullability: android.os.StrictMode.ViolationInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.os.StrictMode.ViolationLogger#log(android.os.StrictMode.ViolationInfo) parameter #0:
+
+MissingNullability: android.os.UserHandle#of(int):
+
+MissingNullability: android.os.VibrationEffect#RINGTONES:
+
+MissingNullability: android.os.VibrationEffect#get(android.net.Uri, android.content.Context) parameter #0:
+
+MissingNullability: android.os.VibrationEffect#get(android.net.Uri, android.content.Context) parameter #1:
+
+MissingNullability: android.os.VibrationEffect#get(int):
+
+MissingNullability: android.os.VibrationEffect#get(int, boolean):
+
+MissingNullability: android.os.VibrationEffect.OneShot#OneShot(android.os.Parcel) parameter #0:
+
+MissingNullability: android.os.VibrationEffect.OneShot#scale(float, int):
+
+MissingNullability: android.os.VibrationEffect.OneShot#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.os.VibrationEffect.Prebaked#Prebaked(android.os.Parcel) parameter #0:
+
+MissingNullability: android.os.VibrationEffect.Prebaked#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.os.VibrationEffect.Waveform#Waveform(android.os.Parcel) parameter #0:
+
+MissingNullability: android.os.VibrationEffect.Waveform#Waveform(long[], int[], int) parameter #0:
+
+MissingNullability: android.os.VibrationEffect.Waveform#Waveform(long[], int[], int) parameter #1:
+
+MissingNullability: android.os.VibrationEffect.Waveform#getAmplitudes():
+
+MissingNullability: android.os.VibrationEffect.Waveform#getTimings():
+
+MissingNullability: android.os.VibrationEffect.Waveform#scale(float, int):
+
+MissingNullability: android.os.VibrationEffect.Waveform#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.os.VintfObject#getHalNamesAndVersions():
+
+MissingNullability: android.os.VintfObject#getSepolicyVersion():
+
+MissingNullability: android.os.VintfObject#getTargetFrameworkCompatibilityMatrixVersion():
+
+MissingNullability: android.os.VintfObject#getVndkSnapshots():
+
+MissingNullability: android.os.VintfObject#report():
+
+MissingNullability: android.os.VintfRuntimeInfo#getCpuInfo():
+
+MissingNullability: android.os.VintfRuntimeInfo#getHardwareId():
+
+MissingNullability: android.os.VintfRuntimeInfo#getKernelVersion():
+
+MissingNullability: android.os.VintfRuntimeInfo#getNodeName():
+
+MissingNullability: android.os.VintfRuntimeInfo#getOsName():
+
+MissingNullability: android.os.VintfRuntimeInfo#getOsRelease():
+
+MissingNullability: android.os.VintfRuntimeInfo#getOsVersion():
+
+MissingNullability: android.os.WorkSource#add(int, String) parameter #1:
+
+MissingNullability: android.os.WorkSource#addReturningNewbs(android.os.WorkSource) parameter #0:
+
+MissingNullability: android.os.WorkSource#getName(int):
+
+MissingNullability: android.os.WorkSource#setReturningDiffs(android.os.WorkSource) parameter #0:
+
+MissingNullability: android.os.health.HealthKeys.Constants#Constants(Class) parameter #0:
+
+MissingNullability: android.os.health.HealthKeys.Constants#getDataType():
+
+MissingNullability: android.os.health.HealthKeys.Constants#getKeys(int):
+
+MissingNullability: android.os.health.HealthStats#HealthStats(android.os.Parcel) parameter #0:
+
+MissingNullability: android.os.health.HealthStatsParceler#HealthStatsParceler(android.os.Parcel) parameter #0:
+
+MissingNullability: android.os.health.HealthStatsParceler#HealthStatsParceler(android.os.health.HealthStatsWriter) parameter #0:
+
+MissingNullability: android.os.health.HealthStatsParceler#getHealthStats():
+
+MissingNullability: android.os.health.HealthStatsParceler#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.os.health.HealthStatsWriter#HealthStatsWriter(android.os.health.HealthKeys.Constants) parameter #0:
+
+MissingNullability: android.os.health.HealthStatsWriter#addMeasurements(int, String, long) parameter #1:
+
+MissingNullability: android.os.health.HealthStatsWriter#addStats(int, String, android.os.health.HealthStatsWriter) parameter #1:
+
+MissingNullability: android.os.health.HealthStatsWriter#addStats(int, String, android.os.health.HealthStatsWriter) parameter #2:
+
+MissingNullability: android.os.health.HealthStatsWriter#addTimers(int, String, android.os.health.TimerStat) parameter #1:
+
+MissingNullability: android.os.health.HealthStatsWriter#addTimers(int, String, android.os.health.TimerStat) parameter #2:
+
+MissingNullability: android.os.health.HealthStatsWriter#flattenToParcel(android.os.Parcel) parameter #0:
+
+MissingNullability: android.os.storage.StorageVolume#getPath():
+
+MissingNullability: android.permission.RuntimePermissionPresentationInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.provider.CalendarContract.Calendars#SYNC_WRITABLE_COLUMNS:
+
+MissingNullability: android.provider.CalendarContract.Events#SYNC_WRITABLE_COLUMNS:
+
+MissingNullability: android.provider.ContactsContract.CommonDataKinds.Phone#ENTERPRISE_CONTENT_URI:
+
+MissingNullability: android.provider.ContactsContract.RawContactsEntity#CORP_CONTENT_URI:
+
+MissingNullability: android.provider.DeviceConfig#getProperty(String, String):
+
+MissingNullability: android.provider.DeviceConfig#getString(String, String, String):
+
+MissingNullability: android.provider.MediaStore#deleteContributedMedia(android.content.Context, String, android.os.UserHandle) parameter #0:
+
+MissingNullability: android.provider.MediaStore#deleteContributedMedia(android.content.Context, String, android.os.UserHandle) parameter #1:
+
+MissingNullability: android.provider.MediaStore#deleteContributedMedia(android.content.Context, String, android.os.UserHandle) parameter #2:
+
+MissingNullability: android.provider.MediaStore#getContributedMediaSize(android.content.Context, String, android.os.UserHandle) parameter #0:
+
+MissingNullability: android.provider.MediaStore#getContributedMediaSize(android.content.Context, String, android.os.UserHandle) parameter #1:
+
+MissingNullability: android.provider.MediaStore#getContributedMediaSize(android.content.Context, String, android.os.UserHandle) parameter #2:
+
+MissingNullability: android.provider.MediaStore#scanFile(android.content.Context, java.io.File):
+
+MissingNullability: android.provider.MediaStore#scanFile(android.content.Context, java.io.File) parameter #0:
+
+MissingNullability: android.provider.MediaStore#scanFile(android.content.Context, java.io.File) parameter #1:
+
+MissingNullability: android.provider.MediaStore#scanFileFromShell(android.content.Context, java.io.File):
+
+MissingNullability: android.provider.MediaStore#scanFileFromShell(android.content.Context, java.io.File) parameter #0:
+
+MissingNullability: android.provider.MediaStore#scanFileFromShell(android.content.Context, java.io.File) parameter #1:
+
+MissingNullability: android.provider.MediaStore#scanVolume(android.content.Context, java.io.File) parameter #0:
+
+MissingNullability: android.provider.MediaStore#scanVolume(android.content.Context, java.io.File) parameter #1:
+
+MissingNullability: android.provider.MediaStore#waitForIdle(android.content.Context) parameter #0:
+
+MissingNullability: android.security.KeyStoreException#KeyStoreException(int, String) parameter #1:
+
+MissingNullability: android.security.keystore.AttestationUtils#attestDeviceIds(android.content.Context, int[], byte[]) parameter #0:
+
+MissingNullability: android.security.keystore.KeyProtection.Builder#setBoundToSpecificSecureUserId(long):
+
+MissingNullability: android.service.autofill.AutofillFieldClassificationService#onBind(android.content.Intent):
+
+MissingNullability: android.service.autofill.AutofillFieldClassificationService#onBind(android.content.Intent) parameter #0:
+
+MissingNullability: android.service.autofill.CompositeUserData#getCategoryIds():
+
+MissingNullability: android.service.autofill.CompositeUserData#getDefaultFieldClassificationArgs():
+
+MissingNullability: android.service.autofill.CompositeUserData#getFieldClassificationAlgorithms():
+
+MissingNullability: android.service.autofill.CompositeUserData#getFieldClassificationArgs():
+
+MissingNullability: android.service.autofill.CompositeUserData#getValues():
+
+MissingNullability: android.service.autofill.CompositeUserData#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.service.autofill.UserData#getFieldClassificationAlgorithms():
+
+MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0:
+
+MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #1:
+
+MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #2:
+
+MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#onUnbind(android.content.Intent) parameter #0:
+
+MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0:
+
+MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #1:
+
+MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #2:
+
+MissingNullability: android.service.notification.Adjustment#Adjustment(String, String, android.os.Bundle, CharSequence, int) parameter #0:
+
+MissingNullability: android.service.notification.Adjustment#Adjustment(String, String, android.os.Bundle, CharSequence, int) parameter #1:
+
+MissingNullability: android.service.notification.Adjustment#Adjustment(String, String, android.os.Bundle, CharSequence, int) parameter #2:
+
+MissingNullability: android.service.notification.Adjustment#Adjustment(String, String, android.os.Bundle, CharSequence, int) parameter #3:
+
+MissingNullability: android.service.notification.Adjustment#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context) parameter #0:
+
+MissingNullability: android.service.notification.NotificationStats#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.service.notification.SnoozeCriterion#SnoozeCriterion(String, CharSequence, CharSequence) parameter #0:
+
+MissingNullability: android.service.notification.SnoozeCriterion#SnoozeCriterion(String, CharSequence, CharSequence) parameter #1:
+
+MissingNullability: android.service.notification.SnoozeCriterion#SnoozeCriterion(String, CharSequence, CharSequence) parameter #2:
+
+MissingNullability: android.service.notification.SnoozeCriterion#SnoozeCriterion(android.os.Parcel) parameter #0:
+
+MissingNullability: android.service.notification.SnoozeCriterion#getConfirmation():
+
+MissingNullability: android.service.notification.SnoozeCriterion#getExplanation():
+
+MissingNullability: android.service.notification.SnoozeCriterion#getId():
+
+MissingNullability: android.service.notification.SnoozeCriterion#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.telecom.Call.Details#getTelecomCallId():
+
+MissingNullability: android.telecom.CallScreeningService.CallResponse.Builder#setShouldScreenCallFurther(boolean):
+
+MissingNullability: android.telecom.Conference#getPrimaryConnection():
+
+MissingNullability: android.telecom.PhoneAccountSuggestionService#onBind(android.content.Intent):
+
+MissingNullability: android.telecom.PhoneAccountSuggestionService#onBind(android.content.Intent) parameter #0:
+
+MissingNullability: android.telephony.CallQuality#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `dest` in method `writeToParcel`
+MissingNullability: android.telephony.DataSpecificRegistrationInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.telephony.LteVopsSupportInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.telephony.NetworkRegistrationInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.telephony.ServiceState#addNetworkRegistrationInfo(android.telephony.NetworkRegistrationInfo) parameter #0:
+
+MissingNullability: android.telephony.ServiceState#setCellBandwidths(int[]) parameter #0:
+
+MissingNullability: android.telephony.SmsManager#checkSmsShortCodeDestination(String, String) parameter #0:
+
+MissingNullability: android.telephony.SmsManager#checkSmsShortCodeDestination(String, String) parameter #1:
+
+MissingNullability: android.telephony.TelephonyManager#checkCarrierPrivilegesForPackage(String) parameter #0:
+
+MissingNullability: android.telephony.TelephonyManager#getCarrierPackageNamesForIntent(android.content.Intent):
+ Missing nullability on method `getCarrierPackageNamesForIntent` return
+MissingNullability: android.telephony.TelephonyManager#getCarrierPackageNamesForIntent(android.content.Intent) parameter #0:
+ Missing nullability on parameter `intent` in method `getCarrierPackageNamesForIntent`
+MissingNullability: android.telephony.TelephonyManager#getLine1AlphaTag():
+
+MissingNullability: android.telephony.TelephonyManager#getRadioHalVersion():
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #0:
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #1:
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #2:
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #3:
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #4:
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #5:
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #6:
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #0:
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #1:
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #2:
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #3:
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #4:
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #5:
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #6:
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #7:
+
+MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #8:
+
+MissingNullability: android.telephony.ims.ImsCallForwardInfo#getNumber():
+ Missing nullability on method `getNumber` return
+MissingNullability: android.telephony.ims.ImsCallForwardInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsCallProfile#ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile) parameter #2:
+ Missing nullability on parameter `callExtras` in method `ImsCallProfile`
+MissingNullability: android.telephony.ims.ImsCallProfile#ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile) parameter #3:
+ Missing nullability on parameter `mediaProfile` in method `ImsCallProfile`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String):
+ Missing nullability on method `getCallExtra` return
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String) parameter #0:
+ Missing nullability on parameter `name` in method `getCallExtra`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String, String):
+ Missing nullability on method `getCallExtra` return
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String, String) parameter #0:
+ Missing nullability on parameter `name` in method `getCallExtra`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String, String) parameter #1:
+ Missing nullability on parameter `defaultValue` in method `getCallExtra`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraBoolean(String) parameter #0:
+ Missing nullability on parameter `name` in method `getCallExtraBoolean`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraBoolean(String, boolean) parameter #0:
+ Missing nullability on parameter `name` in method `getCallExtraBoolean`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraInt(String) parameter #0:
+ Missing nullability on parameter `name` in method `getCallExtraInt`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraInt(String, int) parameter #0:
+ Missing nullability on parameter `name` in method `getCallExtraInt`
+MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtras():
+ Missing nullability on method `getCallExtras` return
+MissingNullability: android.telephony.ims.ImsCallProfile#getMediaProfile():
+ Missing nullability on method `getMediaProfile` return
+MissingNullability: android.telephony.ims.ImsCallProfile#getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `callProfile` in method `getVideoStateFromImsCallProfile`
+MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtra(String, String) parameter #0:
+ Missing nullability on parameter `name` in method `setCallExtra`
+MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtra(String, String) parameter #1:
+ Missing nullability on parameter `value` in method `setCallExtra`
+MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtraBoolean(String, boolean) parameter #0:
+ Missing nullability on parameter `name` in method `setCallExtraBoolean`
+MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtraInt(String, int) parameter #0:
+ Missing nullability on parameter `name` in method `setCallExtraInt`
+MissingNullability: android.telephony.ims.ImsCallProfile#updateCallExtras(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `updateCallExtras`
+MissingNullability: android.telephony.ims.ImsCallProfile#updateCallType(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `updateCallType`
+MissingNullability: android.telephony.ims.ImsCallProfile#updateMediaProfile(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `updateMediaProfile`
+MissingNullability: android.telephony.ims.ImsCallProfile#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionConferenceExtendFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `newSession` in method `callSessionConferenceExtendReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #1:
+ Missing nullability on parameter `profile` in method `callSessionConferenceExtendReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `newSession` in method `callSessionConferenceExtended`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #1:
+ Missing nullability on parameter `profile` in method `callSessionConferenceExtended`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState) parameter #0:
+ Missing nullability on parameter `state` in method `callSessionConferenceStateUpdated`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo) parameter #2:
+ Missing nullability on parameter `reasonInfo` in method `callSessionHandover`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo) parameter #2:
+ Missing nullability on parameter `reasonInfo` in method `callSessionHandoverFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHeld(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionHeld`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHoldFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionHoldFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHoldReceived(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionHoldReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionInitiated(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionInitiated`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionInitiatedFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionInviteParticipantsRequestFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase) parameter #0:
+ Missing nullability on parameter `newSession` in method `callSessionMergeComplete`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionMergeFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `newSession` in method `callSessionMergeStarted`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #1:
+ Missing nullability on parameter `profile` in method `callSessionMergeStarted`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionProgressing`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionRemoveParticipantsRequestFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionResumeFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionResumeFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionResumeReceived(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionResumeReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionResumed(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionResumed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionRttMessageReceived(String) parameter #0:
+ Missing nullability on parameter `rttMessage` in method `callSessionRttMessageReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `callProfile` in method `callSessionRttModifyRequestReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification) parameter #0:
+ Missing nullability on parameter `suppSrvNotification` in method `callSessionSuppServiceReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionTerminated(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionTerminated`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `reasonInfo` in method `callSessionUpdateFailed`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUpdateReceived(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionUpdateReceived`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUpdated(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `callSessionUpdated`
+MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUssdMessageReceived(int, String) parameter #1:
+ Missing nullability on parameter `ussdMessage` in method `callSessionUssdMessageReceived`
+MissingNullability: android.telephony.ims.ImsConferenceState#getConnectionStateForStatus(String) parameter #0:
+ Missing nullability on parameter `status` in method `getConnectionStateForStatus`
+MissingNullability: android.telephony.ims.ImsConferenceState#mParticipants:
+ Missing nullability on field `mParticipants` in class `class android.telephony.ims.ImsConferenceState`
+MissingNullability: android.telephony.ims.ImsConferenceState#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsExternalCallState#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsReasonInfo#ImsReasonInfo(int, int, String) parameter #2:
+ Missing nullability on parameter `extraMessage` in method `ImsReasonInfo`
+MissingNullability: android.telephony.ims.ImsReasonInfo#getExtraMessage():
+ Missing nullability on method `getExtraMessage` return
+MissingNullability: android.telephony.ims.ImsReasonInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsService#createMmTelFeature(int):
+ Missing nullability on method `createMmTelFeature` return
+MissingNullability: android.telephony.ims.ImsService#createRcsFeature(int):
+ Missing nullability on method `createRcsFeature` return
+MissingNullability: android.telephony.ims.ImsService#getConfig(int):
+ Missing nullability on method `getConfig` return
+MissingNullability: android.telephony.ims.ImsService#getRegistration(int):
+ Missing nullability on method `getRegistration` return
+MissingNullability: android.telephony.ims.ImsService#onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) parameter #0:
+ Missing nullability on parameter `c` in method `onUpdateSupportedImsFeatures`
+MissingNullability: android.telephony.ims.ImsService#querySupportedImsFeatures():
+ Missing nullability on method `querySupportedImsFeatures` return
+MissingNullability: android.telephony.ims.ImsSsData#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsSsInfo#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsStreamMediaProfile#copyFrom(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `copyFrom`
+MissingNullability: android.telephony.ims.ImsStreamMediaProfile#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsSuppServiceNotification#ImsSuppServiceNotification(int, int, int, int, String, String[]) parameter #4:
+ Missing nullability on parameter `number` in method `ImsSuppServiceNotification`
+MissingNullability: android.telephony.ims.ImsSuppServiceNotification#ImsSuppServiceNotification(int, int, int, int, String, String[]) parameter #5:
+ Missing nullability on parameter `history` in method `ImsSuppServiceNotification`
+MissingNullability: android.telephony.ims.ImsSuppServiceNotification#history:
+ Missing nullability on field `history` in class `class android.telephony.ims.ImsSuppServiceNotification`
+MissingNullability: android.telephony.ims.ImsSuppServiceNotification#number:
+ Missing nullability on field `number` in class `class android.telephony.ims.ImsSuppServiceNotification`
+MissingNullability: android.telephony.ims.ImsSuppServiceNotification#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `out` in method `writeToParcel`
+MissingNullability: android.telephony.ims.ImsUtListener#onSupplementaryServiceIndication(android.telephony.ims.ImsSsData) parameter #0:
+ Missing nullability on parameter `ssData` in method `onSupplementaryServiceIndication`
+MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
+ Missing nullability on parameter `cbInfo` in method `onUtConfigurationCallBarringQueried`
+MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]) parameter #1:
+ Missing nullability on parameter `cfInfo` in method `onUtConfigurationCallForwardQueried`
+MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
+ Missing nullability on parameter `cwInfo` in method `onUtConfigurationCallWaitingQueried`
+MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationQueried(int, android.os.Bundle) parameter #1:
+ Missing nullability on parameter `configuration` in method `onUtConfigurationQueried`
+MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo) parameter #1:
+ Missing nullability on parameter `error` in method `onUtConfigurationQueryFailed`
+MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo) parameter #1:
+ Missing nullability on parameter `error` in method `onUtConfigurationUpdateFailed`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities) parameter #0:
+ Missing nullability on parameter `CameraCapabilities` in method `changeCameraCapabilities`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #0:
+ Missing nullability on parameter `fromProfile` in method `onSendSessionModifyRequest`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #1:
+ Missing nullability on parameter `toProfile` in method `onSendSessionModifyRequest`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSendSessionModifyResponse(android.telecom.VideoProfile) parameter #0:
+ Missing nullability on parameter `responseProfile` in method `onSendSessionModifyResponse`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetCamera(String) parameter #0:
+ Missing nullability on parameter `cameraId` in method `onSetCamera`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetCamera(String, int) parameter #0:
+ Missing nullability on parameter `cameraId` in method `onSetCamera`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetDisplaySurface(android.view.Surface) parameter #0:
+ Missing nullability on parameter `surface` in method `onSetDisplaySurface`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetPauseImage(android.net.Uri) parameter #0:
+ Missing nullability on parameter `uri` in method `onSetPauseImage`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetPreviewSurface(android.view.Surface) parameter #0:
+ Missing nullability on parameter `surface` in method `onSetPreviewSurface`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#receiveSessionModifyRequest(android.telecom.VideoProfile) parameter #0:
+ Missing nullability on parameter `VideoProfile` in method `receiveSessionModifyRequest`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #1:
+ Missing nullability on parameter `requestedProfile` in method `receiveSessionModifyResponse`
+MissingNullability: android.telephony.ims.ImsVideoCallProvider#receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #2:
+ Missing nullability on parameter `responseProfile` in method `receiveSessionModifyResponse`
+MissingNullability: android.telephony.ims.feature.CapabilityChangeRequest#getCapabilitiesToDisable():
+ Missing nullability on method `getCapabilitiesToDisable` return
+MissingNullability: android.telephony.ims.feature.CapabilityChangeRequest#getCapabilitiesToEnable():
+ Missing nullability on method `getCapabilitiesToEnable` return
+MissingNullability: android.telephony.ims.feature.CapabilityChangeRequest#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `dest` in method `writeToParcel`
+MissingNullability: android.telephony.ims.feature.ImsFeature#changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy) parameter #0:
+ Missing nullability on parameter `request` in method `changeEnabledCapabilities`
+MissingNullability: android.telephony.ims.feature.ImsFeature#changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy) parameter #1:
+ Missing nullability on parameter `c` in method `changeEnabledCapabilities`
+MissingNullability: android.telephony.ims.feature.MmTelFeature#queryCapabilityStatus():
+ Missing nullability on method `queryCapabilityStatus` return
+MissingNullability: android.telephony.ims.feature.MmTelFeature.MmTelCapabilities#MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities) parameter #0:
+ Missing nullability on parameter `c` in method `MmTelCapabilities`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#accept(int, android.telephony.ims.ImsStreamMediaProfile) parameter #1:
+ Missing nullability on parameter `profile` in method `accept`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#deflect(String) parameter #0:
+ Missing nullability on parameter `deflectNumber` in method `deflect`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#extendToConference(String[]) parameter #0:
+ Missing nullability on parameter `participants` in method `extendToConference`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getCallId():
+ Missing nullability on method `getCallId` return
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getCallProfile():
+ Missing nullability on method `getCallProfile` return
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getImsVideoCallProvider():
+ Missing nullability on method `getImsVideoCallProvider` return
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getLocalCallProfile():
+ Missing nullability on method `getLocalCallProfile` return
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getProperty(String):
+ Missing nullability on method `getProperty` return
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getProperty(String) parameter #0:
+ Missing nullability on parameter `name` in method `getProperty`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getRemoteCallProfile():
+ Missing nullability on method `getRemoteCallProfile` return
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#hold(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `hold`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#inviteParticipants(String[]) parameter #0:
+ Missing nullability on parameter `participants` in method `inviteParticipants`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#removeParticipants(String[]) parameter #0:
+ Missing nullability on parameter `participants` in method `removeParticipants`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#resume(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
+ Missing nullability on parameter `profile` in method `resume`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendDtmf(char, android.os.Message) parameter #1:
+ Missing nullability on parameter `result` in method `sendDtmf`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendRttMessage(String) parameter #0:
+ Missing nullability on parameter `rttMessage` in method `sendRttMessage`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendRttModifyRequest(android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `toProfile` in method `sendRttModifyRequest`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendUssd(String) parameter #0:
+ Missing nullability on parameter `ussdMessage` in method `sendUssd`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#setListener(android.telephony.ims.ImsCallSessionListener) parameter #0:
+ Missing nullability on parameter `listener` in method `setListener`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#start(String, android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `callee` in method `start`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#start(String, android.telephony.ims.ImsCallProfile) parameter #1:
+ Missing nullability on parameter `profile` in method `start`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#startConference(String[], android.telephony.ims.ImsCallProfile) parameter #0:
+ Missing nullability on parameter `participants` in method `startConference`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#startConference(String[], android.telephony.ims.ImsCallProfile) parameter #1:
+ Missing nullability on parameter `profile` in method `startConference`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#update(int, android.telephony.ims.ImsStreamMediaProfile) parameter #1:
+ Missing nullability on parameter `profile` in method `update`
+MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase.State#toString(int):
+ Missing nullability on method `toString` return
+MissingNullability: android.telephony.ims.stub.ImsConfigImplBase#getConfigString(int):
+ Missing nullability on method `getConfigString` return
+MissingNullability: android.telephony.ims.stub.ImsConfigImplBase#notifyProvisionedValueChanged(int, String) parameter #1:
+ Missing nullability on parameter `value` in method `notifyProvisionedValueChanged`
+MissingNullability: android.telephony.ims.stub.ImsConfigImplBase#setConfig(int, String) parameter #1:
+ Missing nullability on parameter `value` in method `setConfig`
+MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration#getServiceFeatures():
+ Missing nullability on method `getServiceFeatures` return
+MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration#writeToParcel(android.os.Parcel, int) parameter #0:
+ Missing nullability on parameter `dest` in method `writeToParcel`
+MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration.Builder#addFeature(int, int):
+ Missing nullability on method `addFeature` return
+MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration.Builder#build():
+ Missing nullability on method `build` return
+MissingNullability: android.telephony.ims.stub.ImsMultiEndpointImplBase#onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>) parameter #0:
+ Missing nullability on parameter `externalCallDialogs` in method `onImsExternalCallStateUpdate`
+MissingNullability: android.telephony.ims.stub.ImsRegistrationImplBase#onDeregistered(android.telephony.ims.ImsReasonInfo) parameter #0:
+ Missing nullability on parameter `info` in method `onDeregistered`
+MissingNullability: android.telephony.ims.stub.ImsRegistrationImplBase#onSubscriberAssociatedUriChanged(android.net.Uri[]) parameter #0:
+ Missing nullability on parameter `uris` in method `onSubscriberAssociatedUriChanged`
+MissingNullability: android.telephony.ims.stub.ImsRegistrationImplBase#onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo) parameter #1:
+ Missing nullability on parameter `info` in method `onTechnologyChangeFailed`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#getSmsFormat():
+ Missing nullability on method `getSmsFormat` return
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsReceived(int, String, byte[]) parameter #1:
+ Missing nullability on parameter `format` in method `onSmsReceived`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsReceived(int, String, byte[]) parameter #2:
+ Missing nullability on parameter `pdu` in method `onSmsReceived`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, String, byte[]) parameter #1:
+ Missing nullability on parameter `format` in method `onSmsStatusReportReceived`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, String, byte[]) parameter #2:
+ Missing nullability on parameter `pdu` in method `onSmsStatusReportReceived`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, int, String, byte[]) parameter #2:
+ Missing nullability on parameter `format` in method `onSmsStatusReportReceived`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, int, String, byte[]) parameter #3:
+ Missing nullability on parameter `pdu` in method `onSmsStatusReportReceived`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, String, String, boolean, byte[]) parameter #2:
+ Missing nullability on parameter `format` in method `sendSms`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, String, String, boolean, byte[]) parameter #3:
+ Missing nullability on parameter `smsc` in method `sendSms`
+MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, String, String, boolean, byte[]) parameter #5:
+ Missing nullability on parameter `pdu` in method `sendSms`
+MissingNullability: android.telephony.ims.stub.ImsUtImplBase#queryCallForward(int, String) parameter #1:
+ Missing nullability on parameter `number` in method `queryCallForward`
+MissingNullability: android.telephony.ims.stub.ImsUtImplBase#setListener(android.telephony.ims.ImsUtListener) parameter #0:
+ Missing nullability on parameter `listener` in method `setListener`
+MissingNullability: android.telephony.ims.stub.ImsUtImplBase#transact(android.os.Bundle) parameter #0:
+ Missing nullability on parameter `ssInfo` in method `transact`
+MissingNullability: android.telephony.ims.stub.ImsUtImplBase#updateCallBarring(int, int, String[]) parameter #2:
+ Missing nullability on parameter `barrList` in method `updateCallBarring`
+MissingNullability: android.telephony.ims.stub.ImsUtImplBase#updateCallBarringForServiceClass(int, int, String[], int) parameter #2:
+ Missing nullability on parameter `barrList` in method `updateCallBarringForServiceClass`
+MissingNullability: android.telephony.ims.stub.ImsUtImplBase#updateCallForward(int, int, String, int, int) parameter #2:
+ Missing nullability on parameter `number` in method `updateCallForward`
+MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String):
+
+MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String) parameter #0:
+
+MissingNullability: android.telephony.mbms.FileInfo#FileInfo(android.net.Uri, String) parameter #0:
+
+MissingNullability: android.telephony.mbms.FileInfo#FileInfo(android.net.Uri, String) parameter #1:
+
+MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #0:
+
+MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #1:
+
+MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #2:
+
+MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #3:
+
+MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #4:
+
+MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #5:
+
+MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #6:
+
+MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #0:
+
+MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #1:
+
+MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #2:
+
+MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #3:
+
+MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #4:
+
+MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #5:
+
+MissingNullability: android.telephony.mbms.UriPathPair#getContentUri():
+
+MissingNullability: android.telephony.mbms.UriPathPair#getFilePathUri():
+
+MissingNullability: android.telephony.mbms.UriPathPair#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) parameter #0:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) parameter #1:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) parameter #0:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) parameter #1:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#asBinder():
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#cancelDownload(android.telephony.mbms.DownloadRequest) parameter #0:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#download(android.telephony.mbms.DownloadRequest) parameter #0:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback) parameter #1:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int) parameter #1:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int) parameter #2:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) parameter #0:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) parameter #1:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) parameter #0:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) parameter #1:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) parameter #0:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) parameter #1:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#requestUpdateFileServices(int, java.util.List<java.lang.String>) parameter #1:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#resetDownloadKnowledge(android.telephony.mbms.DownloadRequest) parameter #0:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#setTempFileRootDirectory(int, String) parameter #1:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#onBind(android.content.Intent):
+
+MissingNullability: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#onBind(android.content.Intent) parameter #0:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#asBinder():
+
+MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#getPlaybackUri(int, String) parameter #1:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int) parameter #0:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int) parameter #1:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int) parameter #2:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#requestUpdateStreamingServices(int, java.util.List<java.lang.String>) parameter #1:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback) parameter #1:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback) parameter #2:
+
+MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#stopStreaming(int, String) parameter #1:
+
+MissingNullability: android.telephony.mbms.vendor.VendorUtils#getAppReceiverFromPackageName(android.content.Context, String):
+
+MissingNullability: android.telephony.mbms.vendor.VendorUtils#getAppReceiverFromPackageName(android.content.Context, String) parameter #0:
+
+MissingNullability: android.telephony.mbms.vendor.VendorUtils#getAppReceiverFromPackageName(android.content.Context, String) parameter #1:
+
+MissingNullability: android.text.Selection.MemoryTextWatcher#afterTextChanged(android.text.Editable) parameter #0:
+
+MissingNullability: android.text.Selection.MemoryTextWatcher#beforeTextChanged(CharSequence, int, int, int) parameter #0:
+
+MissingNullability: android.text.Selection.MemoryTextWatcher#onTextChanged(CharSequence, int, int, int) parameter #0:
+
+MissingNullability: android.transition.TransitionManager#getTransition(android.transition.Scene):
+
+MissingNullability: android.transition.TransitionManager#getTransition(android.transition.Scene) parameter #0:
+
+MissingNullability: android.util.FeatureFlagUtils#getAllFeatureFlags():
+
+MissingNullability: android.util.FeatureFlagUtils#isEnabled(android.content.Context, String) parameter #0:
+
+MissingNullability: android.util.FeatureFlagUtils#isEnabled(android.content.Context, String) parameter #1:
+
+MissingNullability: android.util.FeatureFlagUtils#setEnabled(android.content.Context, String, boolean) parameter #0:
+
+MissingNullability: android.util.FeatureFlagUtils#setEnabled(android.content.Context, String, boolean) parameter #1:
+
+MissingNullability: android.util.TimeUtils#formatDuration(long):
+
+MissingNullability: android.util.proto.EncodedBuffer#dumpBuffers(String) parameter #0:
+
+MissingNullability: android.util.proto.EncodedBuffer#dumpByteString(String, String, byte[]) parameter #0:
+
+MissingNullability: android.util.proto.EncodedBuffer#dumpByteString(String, String, byte[]) parameter #1:
+
+MissingNullability: android.util.proto.EncodedBuffer#dumpByteString(String, String, byte[]) parameter #2:
+
+MissingNullability: android.util.proto.EncodedBuffer#getBytes(int):
+
+MissingNullability: android.util.proto.EncodedBuffer#getDebugString():
+
+MissingNullability: android.util.proto.EncodedBuffer#writeRawBuffer(byte[]) parameter #0:
+
+MissingNullability: android.util.proto.EncodedBuffer#writeRawBuffer(byte[], int, int) parameter #0:
+
+MissingNullability: android.util.proto.ProtoOutputStream#ProtoOutputStream(java.io.FileDescriptor) parameter #0:
+
+MissingNullability: android.util.proto.ProtoOutputStream#ProtoOutputStream(java.io.OutputStream) parameter #0:
+
+MissingNullability: android.util.proto.ProtoOutputStream#dump(String) parameter #0:
+
+MissingNullability: android.util.proto.ProtoOutputStream#getBytes():
+
+MissingNullability: android.util.proto.ProtoOutputStream#write(long, String) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#write(long, byte[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writeBytes(long, byte[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writeObject(long, byte[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writePackedBool(long, boolean[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writePackedDouble(long, double[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writePackedEnum(long, int[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writePackedFixed32(long, int[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writePackedFixed64(long, long[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writePackedFloat(long, float[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writePackedInt32(long, int[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writePackedInt64(long, long[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writePackedSFixed32(long, int[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writePackedSFixed64(long, long[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writePackedSInt32(long, int[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writePackedSInt64(long, long[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writePackedUInt32(long, int[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writePackedUInt64(long, long[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writeRepeatedBytes(long, byte[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writeRepeatedObject(long, byte[]) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writeRepeatedString(long, String) parameter #1:
+
+MissingNullability: android.util.proto.ProtoOutputStream#writeString(long, String) parameter #1:
+
+MissingNullability: android.util.proto.ProtoParseException#ProtoParseException(String) parameter #0:
+
+MissingNullability: android.util.proto.ProtoStream#FIELD_TYPE_NAMES:
+
+MissingNullability: android.util.proto.ProtoStream#getFieldCountString(long):
+
+MissingNullability: android.util.proto.ProtoStream#getFieldIdString(long):
+
+MissingNullability: android.util.proto.ProtoStream#getFieldTypeString(long):
+
+MissingNullability: android.util.proto.ProtoStream#getWireTypeString(int):
+
+MissingNullability: android.util.proto.ProtoStream#token2String(long):
+
+MissingNullability: android.util.proto.WireTypeMismatchException#WireTypeMismatchException(String) parameter #0:
+
+MissingNullability: android.view.Choreographer#postCallback(int, Runnable, Object) parameter #1:
+
+MissingNullability: android.view.Choreographer#postCallback(int, Runnable, Object) parameter #2:
+
+MissingNullability: android.view.Choreographer#postCallbackDelayed(int, Runnable, Object, long) parameter #1:
+
+MissingNullability: android.view.Choreographer#postCallbackDelayed(int, Runnable, Object, long) parameter #2:
+
+MissingNullability: android.view.Choreographer#removeCallbacks(int, Runnable, Object) parameter #1:
+
+MissingNullability: android.view.Choreographer#removeCallbacks(int, Runnable, Object) parameter #2:
+
+MissingNullability: android.view.FocusFinder#sort(android.view.View[], int, int, android.view.ViewGroup, boolean) parameter #0:
+
+MissingNullability: android.view.FocusFinder#sort(android.view.View[], int, int, android.view.ViewGroup, boolean) parameter #3:
+
+MissingNullability: android.view.KeyEvent#actionToString(int):
+
+MissingNullability: android.view.View#getTooltipView():
+
+MissingNullability: android.view.View#isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable) parameter #0:
+
+MissingNullability: android.view.View#isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable) parameter #1:
+
+MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.concurrent.Callable<java.io.OutputStream>) parameter #0:
+
+MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.concurrent.Callable<java.io.OutputStream>) parameter #1:
+
+MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.concurrent.Callable<java.io.OutputStream>) parameter #2:
+
+MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.function.Function<android.graphics.Picture,java.lang.Boolean>) parameter #0:
+
+MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.function.Function<android.graphics.Picture,java.lang.Boolean>) parameter #1:
+
+MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.function.Function<android.graphics.Picture,java.lang.Boolean>) parameter #2:
+
+MissingNullability: android.view.WindowManager.LayoutParams#accessibilityTitle:
+
+MissingNullability: android.view.WindowlessViewRoot#WindowlessViewRoot(android.content.Context, android.view.Display, android.view.SurfaceControl) parameter #0:
+
+MissingNullability: android.view.WindowlessViewRoot#WindowlessViewRoot(android.content.Context, android.view.Display, android.view.SurfaceControl) parameter #1:
+
+MissingNullability: android.view.WindowlessViewRoot#WindowlessViewRoot(android.content.Context, android.view.Display, android.view.SurfaceControl) parameter #2:
+
+MissingNullability: android.view.WindowlessViewRoot#addView(android.view.View, android.view.WindowManager.LayoutParams) parameter #0:
+
+MissingNullability: android.view.WindowlessViewRoot#addView(android.view.View, android.view.WindowManager.LayoutParams) parameter #1:
+
+MissingNullability: android.view.WindowlessViewRoot#relayout(android.view.WindowManager.LayoutParams) parameter #0:
+
+MissingNullability: android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener#onAccessibilityServicesStateChanged(android.view.accessibility.AccessibilityManager) parameter #0:
+
+MissingNullability: android.view.accessibility.AccessibilityNodeInfo#setNumInstancesInUseCounter(java.util.concurrent.atomic.AtomicInteger) parameter #0:
+
+MissingNullability: android.view.accessibility.AccessibilityNodeInfo#writeToParcelNoRecycle(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.view.accessibility.AccessibilityWindowInfo#setNumInstancesInUseCounter(java.util.concurrent.atomic.AtomicInteger) parameter #0:
+
+MissingNullability: android.view.contentcapture.ContentCaptureEvent#writeToParcel(android.os.Parcel, int) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#asyncNewChild(int):
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getAutofillId():
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getExtras():
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getHint():
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getNode():
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getTempRect():
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getText():
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#newChild(int):
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#newHtmlInfoBuilder(String):
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#newHtmlInfoBuilder(String) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillHints(String[]) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillId(android.view.autofill.AutofillId) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillId(android.view.autofill.AutofillId, int) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillOptions(CharSequence[]) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillValue(android.view.autofill.AutofillValue) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setClassName(String) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setContentDescription(CharSequence) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setHint(CharSequence) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setHintIdEntry(String) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setHtmlInfo(android.view.ViewStructure.HtmlInfo) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setId(int, String, String, String) parameter #1:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setId(int, String, String, String) parameter #2:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setId(int, String, String, String) parameter #3:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setLocaleList(android.os.LocaleList) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setText(CharSequence) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setText(CharSequence, int, int) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setTextLines(int[], int[]) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setTextLines(int[], int[]) parameter #1:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setTransformation(android.graphics.Matrix) parameter #0:
+
+MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setWebDomain(String) parameter #0:
+
+MissingNullability: android.widget.CalendarView#getBoundsForDate(long, android.graphics.Rect) parameter #1:
+
+MissingNullability: android.widget.ImageView#isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable) parameter #0:
+
+MissingNullability: android.widget.ImageView#isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable) parameter #1:
+
+MissingNullability: android.widget.Magnifier#getMagnifierDefaultSize():
+
+MissingNullability: android.widget.Magnifier#setOnOperationCompleteCallback(android.widget.Magnifier.Callback) parameter #0:
+
+MissingNullability: android.widget.NumberPicker#getDisplayedValueForCurrentSelection():
+
+MissingNullability: android.widget.PopupMenu#getMenuListView():
+
+MissingNullability: android.widget.TimePicker#getAmView():
+
+MissingNullability: android.widget.TimePicker#getHourView():
+
+MissingNullability: android.widget.TimePicker#getMinuteView():
+
+MissingNullability: android.widget.TimePicker#getPmView():
+
+
+
+MutableBareField: android.content.AutofillOptions#appDisabledExpiration:
+
+MutableBareField: android.content.AutofillOptions#augmentedAutofillEnabled:
+
+MutableBareField: android.content.AutofillOptions#disabledActivities:
+
+MutableBareField: android.content.AutofillOptions#whitelistedActivitiesForAugmentedAutofill:
+
+MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#cache:
+
+MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#dbName:
+
+MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#dbSize:
+
+MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#lookaside:
+
+MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#pageSize:
+
+MutableBareField: android.database.sqlite.SQLiteDebug.PagerStats#dbStats:
+
+MutableBareField: android.database.sqlite.SQLiteDebug.PagerStats#largestMemAlloc:
+
+MutableBareField: android.database.sqlite.SQLiteDebug.PagerStats#memoryUsed:
+
+MutableBareField: android.database.sqlite.SQLiteDebug.PagerStats#pageCacheOverflow:
+
+MutableBareField: android.os.StrictMode.ViolationInfo#broadcastIntentAction:
+
+MutableBareField: android.os.StrictMode.ViolationInfo#durationMillis:
+
+MutableBareField: android.os.StrictMode.ViolationInfo#numAnimationsRunning:
+
+MutableBareField: android.os.StrictMode.ViolationInfo#numInstances:
+
+MutableBareField: android.os.StrictMode.ViolationInfo#tags:
+
+MutableBareField: android.os.StrictMode.ViolationInfo#violationNumThisLoop:
+
+MutableBareField: android.os.StrictMode.ViolationInfo#violationUptimeMillis:
+
+
+
+NoByteOrShort: android.media.audiofx.AudioEffect#byteArrayToShort(byte[]):
+
+NoByteOrShort: android.media.audiofx.AudioEffect#setParameter(int, short) parameter #1:
+
+NoByteOrShort: android.media.audiofx.AudioEffect#shortToByteArray(short) parameter #0:
+
+NoByteOrShort: android.os.HwBlob#getInt16(long):
+
+NoByteOrShort: android.os.HwBlob#getInt8(long):
+
+NoByteOrShort: android.os.HwBlob#putInt16(long, short) parameter #1:
+
+NoByteOrShort: android.os.HwBlob#putInt8(long, byte) parameter #1:
+
+NoByteOrShort: android.os.HwParcel#readInt16():
+
+NoByteOrShort: android.os.HwParcel#readInt8():
+
+NoByteOrShort: android.os.HwParcel#writeInt16(short) parameter #0:
+
+NoByteOrShort: android.os.HwParcel#writeInt8(byte) parameter #0:
+
+NoByteOrShort: android.util.proto.EncodedBuffer#readRawByte():
+
+NoByteOrShort: android.util.proto.EncodedBuffer#writeRawByte(byte) parameter #0:
+
+
+
+NoClone: android.net.util.SocketUtils#bindSocketToInterface(java.io.FileDescriptor, String) parameter #0:
+
+NoClone: android.net.util.SocketUtils#closeSocket(java.io.FileDescriptor) parameter #0:
+
+NoClone: android.os.NativeHandle#NativeHandle(java.io.FileDescriptor, boolean) parameter #0:
+
+NoClone: android.os.NativeHandle#getFileDescriptor():
+
+NoClone: android.os.ParcelFileDescriptor#getFile(java.io.FileDescriptor) parameter #0:
+
+NoClone: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0:
+
+NoClone: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0:
+
+NoClone: android.util.proto.ProtoOutputStream#ProtoOutputStream(java.io.FileDescriptor) parameter #0:
+
+
+
+NotCloseable: android.app.ActivityView:
+
+NotCloseable: android.app.prediction.AppPredictor:
+
+NotCloseable: android.os.HwParcel:
+
+NotCloseable: android.telephony.ims.stub.ImsUtImplBase:
+ Classes that release resources (close()) should implement AutoClosable and CloseGuard: class android.telephony.ims.stub.ImsUtImplBase
+
+
+OnNameExpected: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.PrintWriter, String[]):
+
+OnNameExpected: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]):
+
+OnNameExpected: android.service.notification.ConditionProviderService#isBound():
+
+OnNameExpected: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context):
+
+OnNameExpected: android.service.quicksettings.TileService#isQuickSettingsSupported():
+
+OnNameExpected: android.telephony.ims.ImsService#createMmTelFeature(int):
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.telephony.ims.ImsService#createRcsFeature(int):
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.telephony.ims.ImsService#disableIms(int):
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.telephony.ims.ImsService#enableIms(int):
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.telephony.ims.ImsService#getConfig(int):
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.telephony.ims.ImsService#getRegistration(int):
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.telephony.ims.ImsService#querySupportedImsFeatures():
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.telephony.ims.ImsService#readyForFeatureCreation():
+ If implemented by developer, should follow the on<Something> style; otherwise consider marking final
+OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#dispose(int):
+
+OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int):
+
+OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#startGroupCall(int, long, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>, android.telephony.mbms.GroupCallCallback):
+
+OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#stopGroupCall(int, long):
+
+OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#updateGroupCall(int, long, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>):
+
+
+
+PackageLayering: android.util.FeatureFlagUtils:
+
+
+
+ParcelConstructor: android.os.IncidentManager.IncidentReport#IncidentReport(android.os.Parcel):
+
+ParcelConstructor: android.os.IncidentReportArgs#IncidentReportArgs(android.os.Parcel):
+
+ParcelConstructor: android.os.StrictMode.ViolationInfo#ViolationInfo(android.os.Parcel):
+
+ParcelConstructor: android.os.VibrationEffect.OneShot#OneShot(android.os.Parcel):
+
+ParcelConstructor: android.os.VibrationEffect.Prebaked#Prebaked(android.os.Parcel):
+
+ParcelConstructor: android.os.VibrationEffect.Waveform#Waveform(android.os.Parcel):
+
+ParcelConstructor: android.os.health.HealthStatsParceler#HealthStatsParceler(android.os.Parcel):
+
+ParcelConstructor: android.service.notification.SnoozeCriterion#SnoozeCriterion(android.os.Parcel):
+
+
+
+ParcelCreator: android.app.WindowConfiguration:
+
+ParcelCreator: android.net.metrics.ApfProgramEvent:
+
+ParcelCreator: android.net.metrics.ApfStats:
+
+ParcelCreator: android.net.metrics.DhcpClientEvent:
+
+ParcelCreator: android.net.metrics.DhcpErrorEvent:
+
+ParcelCreator: android.net.metrics.IpConnectivityLog.Event:
+
+ParcelCreator: android.net.metrics.IpManagerEvent:
+
+ParcelCreator: android.net.metrics.IpReachabilityEvent:
+
+ParcelCreator: android.net.metrics.NetworkEvent:
+
+ParcelCreator: android.net.metrics.RaEvent:
+
+ParcelCreator: android.net.metrics.ValidationProbeEvent:
+
+ParcelCreator: android.os.VibrationEffect.OneShot:
+
+ParcelCreator: android.os.VibrationEffect.Prebaked:
+
+ParcelCreator: android.os.VibrationEffect.Waveform:
+
+ParcelCreator: android.service.autofill.InternalOnClickAction:
+
+ParcelCreator: android.service.autofill.InternalSanitizer:
+
+ParcelCreator: android.service.autofill.InternalTransformation:
+
+ParcelCreator: android.service.autofill.InternalValidator:
+
+
+
+ParcelNotFinal: android.app.WindowConfiguration:
+
+ParcelNotFinal: android.net.metrics.IpConnectivityLog.Event:
+
+ParcelNotFinal: android.os.IncidentManager.IncidentReport:
+
+ParcelNotFinal: android.os.VibrationEffect.OneShot:
+
+ParcelNotFinal: android.os.VibrationEffect.Prebaked:
+
+ParcelNotFinal: android.os.VibrationEffect.Waveform:
+
+ParcelNotFinal: android.os.health.HealthStatsParceler:
+
+ParcelNotFinal: android.service.autofill.InternalOnClickAction:
+
+ParcelNotFinal: android.service.autofill.InternalSanitizer:
+
+ParcelNotFinal: android.service.autofill.InternalTransformation:
+
+ParcelNotFinal: android.service.autofill.InternalValidator:
+
+
+
+ProtectedMember: android.app.ActivityView#onVisibilityChanged(android.view.View, int):
+
+ProtectedMember: android.app.AppDetailsActivity#onCreate(android.os.Bundle):
+
+ProtectedMember: android.os.VibrationEffect#scale(int, float, int):
+
+ProtectedMember: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]):
+
+ProtectedMember: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.PrintWriter, String[]):
+
+ProtectedMember: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]):
+
+ProtectedMember: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context):
+
+ProtectedMember: android.util.proto.ProtoStream#FIELD_TYPE_NAMES:
+
+ProtectedMember: android.view.View#resetResolvedDrawables():
+
+ProtectedMember: android.view.ViewGroup#resetResolvedDrawables():
+
+
+
+RawAidl: android.telephony.mbms.vendor.MbmsDownloadServiceBase:
+
+RawAidl: android.telephony.mbms.vendor.MbmsStreamingServiceBase:
+
+
+
+RethrowRemoteException: android.app.ActivityManager#resumeAppSwitches():
+
+RethrowRemoteException: android.os.HwBinder#getService(String, String):
+
+RethrowRemoteException: android.os.HwBinder#getService(String, String, boolean):
+
+RethrowRemoteException: android.os.HwBinder#onTransact(int, android.os.HwParcel, android.os.HwParcel, int):
+
+RethrowRemoteException: android.os.HwBinder#registerService(String):
+
+RethrowRemoteException: android.os.HwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int):
+
+RethrowRemoteException: android.os.IHwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int):
+
+RethrowRemoteException: android.telephony.ims.ImsService#onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration):
+ Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause)
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#cancelDownload(android.telephony.mbms.DownloadRequest):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#dispose(int):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#download(android.telephony.mbms.DownloadRequest):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#listPendingDownloads(int):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#requestUpdateFileServices(int, java.util.List<java.lang.String>):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#resetDownloadKnowledge(android.telephony.mbms.DownloadRequest):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#setTempFileRootDirectory(int, String):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#dispose(int):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#dispose(int):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#getPlaybackUri(int, String):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#requestUpdateStreamingServices(int, java.util.List<java.lang.String>):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback):
+
+RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#stopStreaming(int, String):
+
+
+
+SamShouldBeLast: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int):
+
+SamShouldBeLast: android.app.role.RoleManager#addOnRoleHoldersChangedListenerAsUser(java.util.concurrent.Executor, android.app.role.OnRoleHoldersChangedListener, android.os.UserHandle):
+
+SamShouldBeLast: android.app.role.RoleManager#removeOnRoleHoldersChangedListenerAsUser(android.app.role.OnRoleHoldersChangedListener, android.os.UserHandle):
+
+SamShouldBeLast: android.database.sqlite.SQLiteDebug#dump(android.util.Printer, String[]):
+
+SamShouldBeLast: android.database.sqlite.SQLiteDirectCursorDriver#query(android.database.sqlite.SQLiteDatabase.CursorFactory, String[]):
+
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, java.util.concurrent.Executor, android.location.LocationListener):
+
+SamShouldBeLast: android.os.BugreportManager#startBugreport(android.os.ParcelFileDescriptor, android.os.ParcelFileDescriptor, android.os.BugreportParams, java.util.concurrent.Executor, android.os.BugreportManager.BugreportCallback):
+
+SamShouldBeLast: android.os.IHwBinder#linkToDeath(android.os.IHwBinder.DeathRecipient, long):
+
+SamShouldBeLast: android.os.StrictMode.ViolationInfo#dump(android.util.Printer, String):
+
+SamShouldBeLast: android.permission.PermissionControllerManager#getAppPermissions(String, android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, android.os.Handler):
+
+SamShouldBeLast: android.permission.PermissionControllerManager#revokeRuntimePermissions(java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, java.util.concurrent.Executor, android.permission.PermissionControllerManager.OnRevokeRuntimePermissionsCallback):
+
+SamShouldBeLast: android.service.autofill.CharSequenceTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int):
+
+SamShouldBeLast: android.service.autofill.DateTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int):
+
+SamShouldBeLast: android.service.autofill.ImageTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int):
+
+SamShouldBeLast: android.service.autofill.InternalTransformation#batchApply(android.service.autofill.ValueFinder, android.widget.RemoteViews, java.util.ArrayList<android.util.Pair<java.lang.Integer,android.service.autofill.InternalTransformation>>):
+
+SamShouldBeLast: android.telephony.ims.ImsMmTelManager#getFeatureState(java.util.function.Consumer<java.lang.Integer>, java.util.concurrent.Executor):
+ SAM-compatible parameters (such as parameter 1, "callback", in android.telephony.ims.ImsMmTelManager.getFeatureState) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.view.Choreographer#postCallback(int, Runnable, Object):
+
+SamShouldBeLast: android.view.Choreographer#postCallbackDelayed(int, Runnable, Object, long):
+
+SamShouldBeLast: android.view.Choreographer#removeCallbacks(int, Runnable, Object):
+
+SamShouldBeLast: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.function.Function<android.graphics.Picture,java.lang.Boolean>):
+
+SamShouldBeLast: android.view.accessibility.AccessibilityManager#addAccessibilityServicesStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener, android.os.Handler):
+
+
+
+ServiceName: android.Manifest.permission#BIND_CELL_BROADCAST_SERVICE:
+
+ServiceName: android.app.AppOpsManager#OPSTR_BIND_ACCESSIBILITY_SERVICE:
+
+ServiceName: android.provider.Settings.Secure#ACCESSIBILITY_SHORTCUT_TARGET_SERVICE:
+
+ServiceName: android.provider.Settings.Secure#AUTOFILL_SERVICE:
+
+ServiceName: android.provider.Settings.Secure#VOICE_INTERACTION_SERVICE:
+
+
+
+SetterReturnsThis: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener):
+
+SetterReturnsThis: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener):
+
+
+
+StaticUtils: android.os.health.HealthKeys:
+
+StaticUtils: android.service.autofill.InternalTransformation:
+
+StaticUtils: android.telephony.mbms.vendor.VendorUtils:
+
+StaticUtils: android.util.FeatureFlagUtils:
+
+StaticUtils: android.util.proto.ProtoStream:
+
+
+
+StreamFiles: android.os.Environment#buildPath(java.io.File, java.lang.String...):
+
+StreamFiles: android.os.FileUtils#contains(java.io.File, java.io.File):
+
+StreamFiles: android.provider.MediaStore#scanFile(android.content.Context, java.io.File):
+
+StreamFiles: android.provider.MediaStore#scanFileFromShell(android.content.Context, java.io.File):
+
+StreamFiles: android.provider.MediaStore#scanVolume(android.content.Context, java.io.File):
+
+
+
+UseParcelFileDescriptor: android.util.proto.ProtoOutputStream#ProtoOutputStream(java.io.FileDescriptor) parameter #0:
+
+
+
+UserHandle: android.app.admin.DevicePolicyManager#getOwnerInstalledCaCerts(android.os.UserHandle):
+
+UserHandle: android.app.role.RoleManager#addOnRoleHoldersChangedListenerAsUser(java.util.concurrent.Executor, android.app.role.OnRoleHoldersChangedListener, android.os.UserHandle):
+
+UserHandle: android.app.role.RoleManager#addRoleHolderAsUser(String, String, int, android.os.UserHandle, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Boolean>):
+
+UserHandle: android.app.role.RoleManager#clearRoleHoldersAsUser(String, int, android.os.UserHandle, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Boolean>):
+
+UserHandle: android.app.role.RoleManager#getRoleHoldersAsUser(String, android.os.UserHandle):
+
+UserHandle: android.app.role.RoleManager#removeOnRoleHoldersChangedListenerAsUser(android.app.role.OnRoleHoldersChangedListener, android.os.UserHandle):
+
+UserHandle: android.app.role.RoleManager#removeRoleHolderAsUser(String, String, int, android.os.UserHandle, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Boolean>):
+
+UserHandle: android.content.pm.PackageManager#getInstallReason(String, android.os.UserHandle):
+
+UserHandle: android.content.pm.PackageManager#getPermissionFlags(String, String, android.os.UserHandle):
+
+UserHandle: android.content.pm.PackageManager#grantRuntimePermission(String, String, android.os.UserHandle):
+
+UserHandle: android.content.pm.PackageManager#revokeRuntimePermission(String, String, android.os.UserHandle):
+
+UserHandle: android.content.pm.PackageManager#updatePermissionFlags(String, String, int, int, android.os.UserHandle):
+
+UserHandle: android.location.LocationManager#setLocationEnabledForUser(boolean, android.os.UserHandle):
+
+UserHandle: android.permission.PermissionControllerManager#applyStagedRuntimePermissionBackup(String, android.os.UserHandle, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Boolean>):
+
+UserHandle: android.permission.PermissionControllerManager#getRuntimePermissionBackup(android.os.UserHandle, java.util.concurrent.Executor, java.util.function.Consumer<byte[]>):
+
+UserHandle: android.permission.PermissionControllerManager#stageAndApplyRuntimePermissionsBackup(byte[], android.os.UserHandle):
+
+
+
+UserHandleName: android.app.ActivityView#startActivity(android.content.Intent, android.os.UserHandle):
+
+UserHandleName: android.content.AutofillOptions:
+
+UserHandleName: android.content.ContentCaptureOptions:
+
+UserHandleName: android.os.IncidentReportArgs:
+
+UserHandleName: android.provider.MediaStore#deleteContributedMedia(android.content.Context, String, android.os.UserHandle):
+
+UserHandleName: android.provider.MediaStore#getContributedMediaSize(android.content.Context, String, android.os.UserHandle):
+
+
+
+VisiblySynchronized: PsiClassObjectAccessExpression:
+
+VisiblySynchronized: PsiThisExpression:
+
+VisiblySynchronized: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int):
+
+VisiblySynchronized: android.app.ActivityManager#removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener):
+
+VisiblySynchronized: android.content.ContentProviderClient#setDetectNotResponding(long):
+
+VisiblySynchronized: android.content.res.AssetManager#getApkPaths():
+
+VisiblySynchronized: android.content.res.AssetManager#getLastResourceResolution():
+
+VisiblySynchronized: android.content.res.AssetManager#getOverlayablesToString(String):
+
+VisiblySynchronized: android.content.res.AssetManager#setResourceResolutionLoggingEnabled(boolean):
+
+VisiblySynchronized: android.os.MessageQueue#removeSyncBarrier(int):
+
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 55dbc17..7e278e9 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -508,7 +508,7 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- provider.insert(resolveCallingPackage(), mUri, mContentValues);
+ provider.insert(resolveCallingPackage(), null, mUri, mContentValues);
}
}
@@ -522,7 +522,7 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- provider.delete(resolveCallingPackage(), mUri, mWhere, null);
+ provider.delete(resolveCallingPackage(), null, mUri, mWhere, null);
}
}
@@ -557,7 +557,7 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- Bundle result = provider.call(null, mUri.getAuthority(), mMethod, mArg, mExtras);
+ Bundle result = provider.call(null, null, mUri.getAuthority(), mMethod, mArg, mExtras);
if (result != null) {
result.size(); // unpack
}
@@ -584,7 +584,7 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- try (ParcelFileDescriptor fd = provider.openFile(null, mUri, "r", null, null)) {
+ try (ParcelFileDescriptor fd = provider.openFile(null, null, mUri, "r", null, null)) {
FileUtils.copy(fd.getFileDescriptor(), FileDescriptor.out);
}
}
@@ -597,7 +597,7 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- try (ParcelFileDescriptor fd = provider.openFile(null, mUri, "w", null, null)) {
+ try (ParcelFileDescriptor fd = provider.openFile(null, null, mUri, "w", null, null)) {
FileUtils.copy(FileDescriptor.in, fd.getFileDescriptor());
}
}
@@ -616,7 +616,7 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- Cursor cursor = provider.query(resolveCallingPackage(), mUri, mProjection,
+ Cursor cursor = provider.query(resolveCallingPackage(), null, mUri, mProjection,
ContentResolver.createSqlQueryBundle(mWhere, null, mSortOrder), null);
if (cursor == null) {
System.out.println("No result found.");
@@ -679,7 +679,7 @@
@Override
public void onExecute(IContentProvider provider) throws Exception {
- provider.update(resolveCallingPackage(), mUri, mContentValues, mWhere, null);
+ provider.update(resolveCallingPackage(), null, mUri, mContentValues, mWhere, null);
}
}
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index f476fcf..c9277a5 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -476,10 +476,28 @@
// initialization only once in Section.cpp.
map<log_id_t, log_time> LogSection::gLastLogsRetrieved;
-LogSection::LogSection(int id, log_id_t logID) : WorkerThreadSection(id), mLogID(logID) {
- name = "logcat ";
- name += android_log_id_to_name(logID);
- switch (logID) {
+LogSection::LogSection(int id, const char* logID, ...) : WorkerThreadSection(id), mLogMode(logModeBase) {
+ name = "logcat -b ";
+ name += logID;
+
+ va_list args;
+ va_start(args, logID);
+ mLogID = android_name_to_log_id(logID);
+ while(true) {
+ const char* arg = va_arg(args, const char*);
+ if (arg == NULL) {
+ break;
+ }
+ if (!strcmp(arg, "-L")) {
+ // Read from last logcat buffer
+ mLogMode = mLogMode | ANDROID_LOG_PSTORE;
+ }
+ name += " ";
+ name += arg;
+ }
+ va_end(args);
+
+ switch (mLogID) {
case LOG_ID_EVENTS:
case LOG_ID_STATS:
case LOG_ID_SECURITY:
@@ -512,9 +530,8 @@
// Open log buffer and getting logs since last retrieved time if any.
unique_ptr<logger_list, void (*)(logger_list*)> loggers(
gLastLogsRetrieved.find(mLogID) == gLastLogsRetrieved.end()
- ? android_logger_list_alloc(ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, 0)
- : android_logger_list_alloc_time(ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
- gLastLogsRetrieved[mLogID], 0),
+ ? android_logger_list_alloc(mLogMode, 0, 0)
+ : android_logger_list_alloc_time(mLogMode, gLastLogsRetrieved[mLogID], 0),
android_logger_list_free);
if (android_logger_open(loggers.get(), mLogID) == NULL) {
diff --git a/cmds/incidentd/src/Section.h b/cmds/incidentd/src/Section.h
index c9b8056..fcf12f7 100644
--- a/cmds/incidentd/src/Section.h
+++ b/cmds/incidentd/src/Section.h
@@ -146,8 +146,11 @@
// global last log retrieved timestamp for each log_id_t.
static map<log_id_t, log_time> gLastLogsRetrieved;
+ // log mode: read only & non blocking.
+ const static int logModeBase = ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK;
+
public:
- LogSection(int id, log_id_t logID);
+ LogSection(int id, const char* logID, ...);
virtual ~LogSection();
virtual status_t BlockingCall(int pipeWriteFd) const;
@@ -155,6 +158,7 @@
private:
log_id_t mLogID;
bool mBinary;
+ int mLogMode;
};
/**
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 6c3dff2..91cadc9 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -200,6 +200,10 @@
}
void StatsLogProcessor::OnLogEvent(LogEvent* event) {
+ OnLogEvent(event, getElapsedRealtimeNs());
+}
+
+void StatsLogProcessor::OnLogEvent(LogEvent* event, int64_t elapsedRealtimeNs) {
std::lock_guard<std::mutex> lock(mMetricsMutex);
#ifdef VERY_VERBOSE_PRINTING
@@ -207,9 +211,9 @@
ALOGI("%s", event->ToString().c_str());
}
#endif
- const int64_t currentTimestampNs = event->GetElapsedTimestampNs();
+ const int64_t eventElapsedTimeNs = event->GetElapsedTimestampNs();
- resetIfConfigTtlExpiredLocked(currentTimestampNs);
+ resetIfConfigTtlExpiredLocked(eventElapsedTimeNs);
StatsdStats::getInstance().noteAtomLogged(
event->GetTagId(), event->GetElapsedTimestampNs() / NS_PER_SEC);
@@ -264,15 +268,16 @@
uidsWithActiveConfigsChanged.insert(uid);
StatsdStats::getInstance().noteActiveStatusChanged(pair.first, isCurActive);
}
- flushIfNecessaryLocked(event->GetElapsedTimestampNs(), pair.first, *(pair.second));
+ flushIfNecessaryLocked(pair.first, *(pair.second));
}
+ // Don't use the event timestamp for the guardrail.
for (int uid : uidsWithActiveConfigsChanged) {
// Send broadcast so that receivers can pull data.
auto lastBroadcastTime = mLastActivationBroadcastTimes.find(uid);
if (lastBroadcastTime != mLastActivationBroadcastTimes.end()) {
- if (currentTimestampNs - lastBroadcastTime->second <
- StatsdStats::kMinActivationBroadcastPeriodNs) {
+ if (elapsedRealtimeNs - lastBroadcastTime->second <
+ StatsdStats::kMinActivationBroadcastPeriodNs) {
StatsdStats::getInstance().noteActivationBroadcastGuardrailHit(uid);
VLOG("StatsD would've sent an activation broadcast but the rate limit stopped us.");
return;
@@ -282,13 +287,13 @@
if (activeConfigs != activeConfigsPerUid.end()) {
if (mSendActivationBroadcast(uid, activeConfigs->second)) {
VLOG("StatsD sent activation notice for uid %d", uid);
- mLastActivationBroadcastTimes[uid] = currentTimestampNs;
+ mLastActivationBroadcastTimes[uid] = elapsedRealtimeNs;
}
} else {
std::vector<int64_t> emptyActiveConfigs;
if (mSendActivationBroadcast(uid, emptyActiveConfigs)) {
VLOG("StatsD sent EMPTY activation notice for uid %d", uid);
- mLastActivationBroadcastTimes[uid] = currentTimestampNs;
+ mLastActivationBroadcastTimes[uid] = elapsedRealtimeNs;
}
}
}
@@ -550,22 +555,23 @@
}
}
-void StatsLogProcessor::flushIfNecessaryLocked(
- int64_t timestampNs, const ConfigKey& key, MetricsManager& metricsManager) {
+void StatsLogProcessor::flushIfNecessaryLocked(const ConfigKey& key,
+ MetricsManager& metricsManager) {
+ int64_t elapsedRealtimeNs = getElapsedRealtimeNs();
auto lastCheckTime = mLastByteSizeTimes.find(key);
if (lastCheckTime != mLastByteSizeTimes.end()) {
- if (timestampNs - lastCheckTime->second < StatsdStats::kMinByteSizeCheckPeriodNs) {
+ if (elapsedRealtimeNs - lastCheckTime->second < StatsdStats::kMinByteSizeCheckPeriodNs) {
return;
}
}
// We suspect that the byteSize() computation is expensive, so we set a rate limit.
size_t totalBytes = metricsManager.byteSize();
- mLastByteSizeTimes[key] = timestampNs;
+ mLastByteSizeTimes[key] = elapsedRealtimeNs;
bool requestDump = false;
- if (totalBytes >
- StatsdStats::kMaxMetricsBytesPerConfig) { // Too late. We need to start clearing data.
- metricsManager.dropData(timestampNs);
+ if (totalBytes > StatsdStats::kMaxMetricsBytesPerConfig) {
+ // Too late. We need to start clearing data.
+ metricsManager.dropData(elapsedRealtimeNs);
StatsdStats::getInstance().noteDataDropped(key, totalBytes);
VLOG("StatsD had to toss out metrics for %s", key.ToString().c_str());
} else if ((totalBytes > StatsdStats::kBytesPerConfigTriggerGetData) ||
@@ -580,7 +586,8 @@
// Send broadcast so that receivers can pull data.
auto lastBroadcastTime = mLastBroadcastTimes.find(key);
if (lastBroadcastTime != mLastBroadcastTimes.end()) {
- if (timestampNs - lastBroadcastTime->second < StatsdStats::kMinBroadcastPeriodNs) {
+ if (elapsedRealtimeNs - lastBroadcastTime->second <
+ StatsdStats::kMinBroadcastPeriodNs) {
VLOG("StatsD would've sent a broadcast but the rate limit stopped us.");
return;
}
@@ -588,7 +595,7 @@
if (mSendBroadcast(key)) {
mOnDiskDataConfigs.erase(key);
VLOG("StatsD triggered data fetch for %s", key.ToString().c_str());
- mLastBroadcastTimes[key] = timestampNs;
+ mLastBroadcastTimes[key] = elapsedRealtimeNs;
StatsdStats::getInstance().noteBroadcastSent(key);
}
}
diff --git a/cmds/statsd/src/StatsLogProcessor.h b/cmds/statsd/src/StatsLogProcessor.h
index 8292a3a..17f2770 100644
--- a/cmds/statsd/src/StatsLogProcessor.h
+++ b/cmds/statsd/src/StatsLogProcessor.h
@@ -128,13 +128,13 @@
std::unordered_map<ConfigKey, sp<MetricsManager>> mMetricsManagers;
- std::unordered_map<ConfigKey, long> mLastBroadcastTimes;
+ std::unordered_map<ConfigKey, int64_t> mLastBroadcastTimes;
// Last time we sent a broadcast to this uid that the active configs had changed.
- std::unordered_map<int, long> mLastActivationBroadcastTimes;
+ std::unordered_map<int, int64_t> mLastActivationBroadcastTimes;
// Tracks when we last checked the bytes consumed for each config key.
- std::unordered_map<ConfigKey, long> mLastByteSizeTimes;
+ std::unordered_map<ConfigKey, int64_t> mLastByteSizeTimes;
// Tracks which config keys has metric reports on disk
std::set<ConfigKey> mOnDiskDataConfigs;
@@ -147,6 +147,8 @@
sp<AlarmMonitor> mPeriodicAlarmMonitor;
+ void OnLogEvent(LogEvent* event, int64_t elapsedRealtimeNs);
+
void resetIfConfigTtlExpiredLocked(const int64_t timestampNs);
void OnConfigUpdatedLocked(
@@ -176,8 +178,7 @@
/* Check if we should send a broadcast if approaching memory limits and if we're over, we
* actually delete the data. */
- void flushIfNecessaryLocked(int64_t timestampNs, const ConfigKey& key,
- MetricsManager& metricsManager);
+ void flushIfNecessaryLocked(const ConfigKey& key, MetricsManager& metricsManager);
// Maps the isolated uid in the log event to host uid if the log event contains uid fields.
void mapIsolatedUidToHostUidIfNecessaryLocked(LogEvent* event) const;
@@ -205,7 +206,7 @@
int64_t mLastTimestampSeen = 0;
- long mLastPullerCacheClearTimeSec = 0;
+ int64_t mLastPullerCacheClearTimeSec = 0;
// Last time we wrote data to disk.
int64_t mLastWriteTimeNs = 0;
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 8618d4d..c196c61 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -337,6 +337,8 @@
CameraActionEvent camera_action_event = 227;
AppCompatibilityChangeReported app_compatibility_change_reported =
228 [(allow_from_any_uid) = true];
+ PerfettoUploaded perfetto_uploaded =
+ 229 [(log_from_module) = "perfetto"];
}
// Pulled events will start at field 10000.
@@ -7239,3 +7241,37 @@
optional Source source = 4;
}
+
+/**
+ * Logged from
+ * external/perfetto/src/perfetto_cmd/perfetto_cmd.cc
+ */
+message PerfettoUploaded {
+ enum Event {
+ PERFETTO_UNDEFINED = 0;
+ PERFETTO_TRACE_BEGIN = 1;
+ PERFETTO_BACKGROUND_TRACE_BEGIN = 2;
+ PERFETTO_ON_CONNECT = 3;
+ PERFETTO_ON_TRACING_DISABLED = 4;
+ PERFETTO_UPLOAD_DROPBOX_BEGIN = 5;
+ PERFETTO_UPLOAD_DROPBOX_SUCCESS = 6;
+ PERFETTO_UPLOAD_DROPBOX_FAILURE = 7;
+ PERFETTO_UPLOAD_INCIDENT_BEGIN = 8;
+ PERFETTO_UPLOAD_INCIDENT_SUCCESS = 9;
+ PERFETTO_UPLOAD_INCIDENT_FAILURE = 10;
+ PERFETTO_FINALIZE_TRACE_AND_EXIT = 11;
+ PERFETTO_TRIGGER_BEGIN = 12;
+ PERFETTO_TRIGGER_SUCCESS = 13;
+ PERFETTO_TRIGGER_FAILURE = 14;
+ PERFETTO_HIT_GUARDRAILS = 15;
+ PERFETTO_ON_TIMEOUT = 16;
+ PERFETTO_NOT_UPLOADING_EMPTY_TRACE = 17;
+ }
+
+ // Which stage of the pipeline we are reporting from.
+ optional Event event = 1;
+
+ // UUID matching the one set inside the SystemInfo trace packet.
+ optional int64 trace_uuid_lsb = 2;
+ optional int64 trace_uuid_msb = 3;
+}
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 6fd0327..0ee156b 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -650,6 +650,7 @@
ret.setDouble(value.mValue.double_value);
break;
default:
+ return false;
break;
}
return true;
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 460b9e0..69e11ed 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -76,9 +76,9 @@
// Expect only the first flush to trigger a check for byte size since the last two are
// rate-limited.
EXPECT_CALL(mockMetricsManager, byteSize()).Times(1);
- p.flushIfNecessaryLocked(99, key, mockMetricsManager);
- p.flushIfNecessaryLocked(100, key, mockMetricsManager);
- p.flushIfNecessaryLocked(101, key, mockMetricsManager);
+ p.flushIfNecessaryLocked(key, mockMetricsManager);
+ p.flushIfNecessaryLocked(key, mockMetricsManager);
+ p.flushIfNecessaryLocked(key, mockMetricsManager);
}
TEST(StatsLogProcessorTest, TestRateLimitBroadcast) {
@@ -103,7 +103,7 @@
StatsdStats::kMaxMetricsBytesPerConfig * .95)));
// Expect only one broadcast despite always returning a size that should trigger broadcast.
- p.flushIfNecessaryLocked(1, key, mockMetricsManager);
+ p.flushIfNecessaryLocked(key, mockMetricsManager);
EXPECT_EQ(1, broadcastCount);
// b/73089712
@@ -136,7 +136,7 @@
EXPECT_CALL(mockMetricsManager, dropData(_)).Times(1);
// Expect to call the onDumpReport and skip the broadcast.
- p.flushIfNecessaryLocked(1, key, mockMetricsManager);
+ p.flushIfNecessaryLocked(key, mockMetricsManager);
EXPECT_EQ(0, broadcastCount);
}
diff --git a/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
index 5da0fca..9093155 100644
--- a/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
@@ -271,19 +271,19 @@
// Turn screen off.
event = CreateScreenStateChangedEvent(
android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 2 * NS_PER_SEC); // 0:02
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 2 * NS_PER_SEC);
// Turn screen on.
const int64_t durationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC; // 0:05
event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), durationStartNs);
// Activate metric.
const int64_t activationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC; // 0:10
const int64_t activationEndNs =
activationStartNs + event_activation1->ttl_seconds() * NS_PER_SEC; // 0:40
event = CreateAppCrashEvent(111, activationStartNs);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), activationStartNs);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 1);
@@ -296,7 +296,7 @@
// Expire activation.
const int64_t expirationNs = activationEndNs + 7 * NS_PER_SEC;
event = CreateScreenBrightnessChangedEvent(64, expirationNs); // 0:47
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), expirationNs);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_FALSE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 2);
@@ -310,24 +310,24 @@
// Turn off screen 10 seconds after activation expiration.
const int64_t durationEndNs = activationEndNs + 10 * NS_PER_SEC; // 0:50
event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(),durationEndNs);
// Turn screen on.
const int64_t duration2StartNs = durationEndNs + 5 * NS_PER_SEC; // 0:55
event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, duration2StartNs);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), duration2StartNs);
// Turn off screen.
const int64_t duration2EndNs = duration2StartNs + 10 * NS_PER_SEC; // 1:05
event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, duration2EndNs);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), duration2EndNs);
// Activate metric.
const int64_t activation2StartNs = duration2EndNs + 5 * NS_PER_SEC; // 1:10
const int64_t activation2EndNs =
activation2StartNs + event_activation1->ttl_seconds() * NS_PER_SEC; // 1:40
event = CreateAppCrashEvent(211, activation2StartNs);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), activation2StartNs);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 3);
diff --git a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
index f1b6029..b6a6492 100644
--- a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
@@ -290,14 +290,14 @@
std::unique_ptr<LogEvent> event;
event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_FALSE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 0);
// Activated by battery save mode.
event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 1);
@@ -312,12 +312,12 @@
// First processed event.
event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
// Activated by screen on event.
event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
bucketStartTimeNs + 20);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
@@ -330,7 +330,7 @@
// 2nd processed event.
// The activation by screen_on event expires, but the one by battery save mode is still active.
event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
@@ -344,11 +344,11 @@
// 3rd processed event.
event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
// All activations expired.
event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_FALSE(metricProducer->mIsActive);
// New broadcast since the config is no longer active.
@@ -364,7 +364,7 @@
// Re-activate metric via screen on.
event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 3);
@@ -379,7 +379,7 @@
// 4th processed event.
event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
@@ -509,14 +509,14 @@
std::unique_ptr<LogEvent> event;
event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_FALSE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 0);
// Activated by battery save mode.
event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 1);
@@ -532,12 +532,12 @@
// First processed event.
event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
// Activated by screen on event.
event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
bucketStartTimeNs + 20);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
@@ -551,7 +551,7 @@
// 2nd processed event.
// The activation by screen_on event expires, but the one by battery save mode is still active.
event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(),bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
@@ -566,11 +566,11 @@
// 3rd processed event.
event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
// All activations expired.
event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_FALSE(metricProducer->mIsActive);
// New broadcast since the config is no longer active.
@@ -587,7 +587,7 @@
// Re-activate metric via screen on.
event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 3);
@@ -603,11 +603,11 @@
// 4th processed event.
event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
// Re-enable battery saver mode activation.
event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 3);
@@ -623,11 +623,11 @@
// 5th processed event.
event = CreateAppCrashEvent(777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
// Cancel battery saver mode activation.
event = CreateScreenBrightnessChangedEvent(64, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 3);
@@ -643,7 +643,7 @@
// Screen-on activation expired.
event = CreateAppCrashEvent(888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_FALSE(metricProducer->mIsActive);
// New broadcast since the config is no longer active.
@@ -658,11 +658,11 @@
EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
event = CreateAppCrashEvent(999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
// Re-enable battery saver mode activation.
event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 5);
@@ -678,7 +678,7 @@
// Cancel battery saver mode activation.
event = CreateScreenBrightnessChangedEvent(140, bucketStartTimeNs + NS_PER_SEC * 60 * 16);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 16);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_FALSE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 6);
@@ -835,14 +835,14 @@
std::unique_ptr<LogEvent> event;
event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_FALSE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 0);
// Activated by battery save mode.
event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 1);
@@ -859,12 +859,12 @@
// First processed event.
event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
// Activated by screen on event.
event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
bucketStartTimeNs + 20);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
@@ -879,7 +879,7 @@
// 2nd processed event.
// The activation by screen_on event expires, but the one by battery save mode is still active.
event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
@@ -895,11 +895,11 @@
// 3rd processed event.
event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
// All activations expired.
event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_FALSE(metricProducer->mIsActive);
// New broadcast since the config is no longer active.
@@ -917,7 +917,7 @@
// Re-activate metric via screen on.
event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 3);
@@ -934,11 +934,11 @@
// 4th processed event.
event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
// Re-enable battery saver mode activation.
event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 3);
@@ -955,11 +955,11 @@
// 5th processed event.
event = CreateAppCrashEvent(777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
// Cancel battery saver mode and screen on activation.
event = CreateScreenBrightnessChangedEvent(64, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_FALSE(metricProducer->mIsActive);
// New broadcast since the config is no longer active.
@@ -976,7 +976,7 @@
// Screen-on activation expired.
event = CreateAppCrashEvent(888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_FALSE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 4);
@@ -991,11 +991,11 @@
EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
event = CreateAppCrashEvent(999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
// Re-enable battery saver mode activation.
event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 5);
@@ -1012,7 +1012,7 @@
// Cancel battery saver mode and screen on activation.
event = CreateScreenBrightnessChangedEvent(140, bucketStartTimeNs + NS_PER_SEC * 60 * 16);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 16);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_FALSE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 6);
@@ -1170,11 +1170,11 @@
// Event that should be ignored.
event = CreateAppCrashEvent(111, bucketStartTimeNs + 1);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 1);
// Activate metric via screen on for 2 minutes.
event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 1);
@@ -1186,11 +1186,11 @@
// 1st processed event.
event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
// Enable battery saver mode activation for 5 minutes.
event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 + 10);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 + 10);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 1);
@@ -1201,12 +1201,12 @@
// 2nd processed event.
event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 + 40);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 + 40);
// Cancel battery saver mode and screen on activation.
int64_t firstDeactivation = bucketStartTimeNs + NS_PER_SEC * 61;
event = CreateScreenBrightnessChangedEvent(64, firstDeactivation);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), firstDeactivation);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_FALSE(metricProducer->mIsActive);
// New broadcast since the config is no longer active.
@@ -1217,11 +1217,11 @@
// Should be ignored
event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 61 + 80);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 61 + 80);
// Re-enable battery saver mode activation.
event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 15);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 15);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 3);
@@ -1233,12 +1233,12 @@
// 3rd processed event.
event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 80);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 80);
// Cancel battery saver mode activation.
int64_t secondDeactivation = bucketStartTimeNs + NS_PER_SEC * 60 * 13;
event = CreateScreenBrightnessChangedEvent(140, secondDeactivation);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), secondDeactivation);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_FALSE(metricProducer->mIsActive);
EXPECT_EQ(broadcastCount, 4);
@@ -1248,7 +1248,7 @@
// Should be ignored.
event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 13 + 80);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13 + 80);
ConfigMetricsReportList reports;
vector<uint8_t> buffer;
@@ -1388,9 +1388,9 @@
std::unique_ptr<LogEvent> event;
event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
event = CreateMoveToForegroundEvent(1111, bucketStartTimeNs + 5);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_FALSE(metricProducer->mIsActive);
EXPECT_FALSE(metricProducer2->mIsActive);
@@ -1398,7 +1398,7 @@
// Activated by battery save mode.
event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_EQ(broadcastCount, 1);
EXPECT_EQ(activeConfigsBroadcast.size(), 1);
@@ -1424,14 +1424,14 @@
// First processed event.
event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
event = CreateMoveToForegroundEvent(2222, bucketStartTimeNs + 15);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
// Activated by screen on event.
event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
bucketStartTimeNs + 20);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
@@ -1455,9 +1455,9 @@
// 2nd processed event.
// The activation by screen_on event expires, but the one by battery save mode is still active.
event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
event = CreateMoveToForegroundEvent(3333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_TRUE(metricProducer->mIsActive);
EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
@@ -1482,15 +1482,15 @@
// 3rd processed event.
event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
event = CreateMoveToForegroundEvent(4444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
// All activations expired.
event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
event = CreateMoveToForegroundEvent(5555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
EXPECT_FALSE(metricsManager->isActive());
// New broadcast since the config is no longer active.
EXPECT_EQ(broadcastCount, 2);
@@ -1517,7 +1517,7 @@
// Re-activate metric via screen on.
event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_EQ(broadcastCount, 3);
EXPECT_EQ(activeConfigsBroadcast.size(), 1);
@@ -1543,13 +1543,13 @@
// 4th processed event.
event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
event = CreateMoveToForegroundEvent(6666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
// Re-enable battery saver mode activation.
event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_EQ(broadcastCount, 3);
EXPECT_EQ(activeConfigsBroadcast.size(), 1);
@@ -1575,13 +1575,13 @@
// 5th processed event.
event = CreateAppCrashEvent(777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
event = CreateMoveToForegroundEvent(7777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
// Cancel battery saver mode and screen on activation.
event = CreateScreenBrightnessChangedEvent(64, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(),bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
EXPECT_FALSE(metricsManager->isActive());
// New broadcast since the config is no longer active.
EXPECT_EQ(broadcastCount, 4);
@@ -1607,9 +1607,9 @@
// Screen-on activation expired.
event = CreateAppCrashEvent(888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
event = CreateMoveToForegroundEvent(8888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_EQ(broadcastCount, 4);
EXPECT_EQ(activeConfigsBroadcast.size(), 0);
@@ -1633,13 +1633,13 @@
EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
event = CreateAppCrashEvent(999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
event = CreateMoveToForegroundEvent(9999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
// Re-enable battery saver mode activation.
event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
EXPECT_TRUE(metricsManager->isActive());
EXPECT_EQ(broadcastCount, 5);
EXPECT_EQ(activeConfigsBroadcast.size(), 1);
@@ -1665,7 +1665,7 @@
// Cancel battery saver mode and screen on activation.
event = CreateScreenBrightnessChangedEvent(140, bucketStartTimeNs + NS_PER_SEC * 60 * 16);
- processor.OnLogEvent(event.get());
+ processor.OnLogEvent(event.get(),bucketStartTimeNs + NS_PER_SEC * 60 * 16);
EXPECT_FALSE(metricsManager->isActive());
EXPECT_EQ(broadcastCount, 6);
EXPECT_EQ(activeConfigsBroadcast.size(), 0);
diff --git a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
index 455e4bb..b23bf5d 100644
--- a/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
+++ b/cmds/uiautomator/library/testrunner-src/com/android/uiautomator/core/ShellUiAutomatorBridge.java
@@ -67,7 +67,7 @@
throw new IllegalStateException("Could not find provider: " + providerName);
}
provider = holder.provider;
- cursor = provider.query(null, Settings.Secure.CONTENT_URI,
+ cursor = provider.query(null, null, Settings.Secure.CONTENT_URI,
new String[] {
Settings.Secure.VALUE
},
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 8d91144..1b9898a 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -200,7 +200,6 @@
android.app.ContextImpl$1
android.app.ContextImpl$ApplicationContentResolver
android.app.ContextImpl
-android.app.DeviceIdleFrameworkInitializer
android.app.DexLoadReporter
android.app.Dialog$ListenersHandler
android.app.Dialog
diff --git a/config/preloaded-classes-extra b/config/preloaded-classes-extra
index 4bfa873..09f393a 100644
--- a/config/preloaded-classes-extra
+++ b/config/preloaded-classes-extra
@@ -1,7 +1,3 @@
-# JobSchedulerFrameworkInitializer must always be preloaded because it registers the job scheduler
-# service wrapper to SystemServiceRegistry.
-android.app.DeviceIdleFrameworkInitializer
-android.app.job.JobSchedulerFrameworkInitializer
android.icu.impl.coll.CollationRoot
android.icu.impl.IDNA2003
android.icu.impl.number.Parse
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 9872e30..738e90a 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2474,15 +2474,10 @@
if (mAutoFillResetNeeded) {
getAutofillManager().onInvisibleForAutofill();
- }
-
- if (isFinishing() && !mAutoFillResetNeeded && mIntent != null
- && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)) {
- // Activity was launched when user tapped a link in the Autofill Save UI - since
- // user launched another activity, the Save UI should not be restored when this
- // activity is finished.
- getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_CANCEL,
- mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN));
+ } else if (mIntent != null
+ && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)
+ && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY)) {
+ restoreAutofillSaveUi();
}
mEnterAnimationComplete = false;
}
@@ -5530,6 +5525,21 @@
*/
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
+ if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)
+ && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY)) {
+ if (TextUtils.equals(getPackageName(),
+ intent.resolveActivity(getPackageManager()).getPackageName())) {
+ // Apply Autofill restore mechanism on the started activity by startActivity()
+ final IBinder token =
+ mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
+ // Remove restore ability from current activity
+ mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
+ mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY);
+ // Put restore token
+ intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
+ intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true);
+ }
+ }
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
@@ -6260,12 +6270,24 @@
// Activity was launched when user tapped a link in the Autofill Save UI - Save UI must
// be restored now.
if (mIntent != null && mIntent.hasExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN)) {
- getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_RESTORE,
- mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN));
+ restoreAutofillSaveUi();
}
}
/**
+ * Restores Autofill Save UI
+ */
+ private void restoreAutofillSaveUi() {
+ final IBinder token =
+ mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
+ // Make only restore Autofill once
+ mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN);
+ mIntent.removeExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY);
+ getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_RESTORE,
+ token);
+ }
+
+ /**
* Call this when your activity is done and should be closed. The
* ActivityResult is propagated back to whoever launched you via
* onActivityResult().
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 7f597fe..1e78fc1 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -163,7 +163,7 @@
}
@Override
- public void onUidStateChanged(int uid, int procState, long procStateSeq) {
+ public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) {
mListener.onUidImportance(uid, RunningAppProcessInfo.procStateToImportanceForClient(
procState, mContext));
}
@@ -432,7 +432,6 @@
public static final int USER_OP_ERROR_RELATED_USERS_CANNOT_STOP = -4;
/**
- * @hide
* Process states, describing the kind of state a particular process is in.
* When updating these, make sure to also check all related references to the
* constant in code, and update these arrays:
@@ -443,7 +442,34 @@
* @see com.android.server.am.ProcessList#sSameAwakePssTimes
* @see com.android.server.am.ProcessList#sTestFirstPssTimes
* @see com.android.server.am.ProcessList#sTestSamePssTimes
+ * @hide
*/
+ @IntDef(flag = false, prefix = { "PROCESS_STATE_" }, value = {
+ PROCESS_STATE_UNKNOWN, // -1
+ PROCESS_STATE_PERSISTENT, // 0
+ PROCESS_STATE_PERSISTENT_UI,
+ PROCESS_STATE_TOP,
+ PROCESS_STATE_BOUND_TOP,
+ PROCESS_STATE_FOREGROUND_SERVICE,
+ PROCESS_STATE_BOUND_FOREGROUND_SERVICE,
+ PROCESS_STATE_IMPORTANT_FOREGROUND,
+ PROCESS_STATE_IMPORTANT_BACKGROUND,
+ PROCESS_STATE_TRANSIENT_BACKGROUND,
+ PROCESS_STATE_BACKUP,
+ PROCESS_STATE_SERVICE,
+ PROCESS_STATE_RECEIVER,
+ PROCESS_STATE_TOP_SLEEPING,
+ PROCESS_STATE_HEAVY_WEIGHT,
+ PROCESS_STATE_HOME,
+ PROCESS_STATE_LAST_ACTIVITY,
+ PROCESS_STATE_CACHED_ACTIVITY,
+ PROCESS_STATE_CACHED_ACTIVITY_CLIENT,
+ PROCESS_STATE_CACHED_RECENT,
+ PROCESS_STATE_CACHED_EMPTY,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ProcessState {}
+
/** @hide Not a real process state. */
public static final int PROCESS_STATE_UNKNOWN = -1;
@@ -459,78 +485,98 @@
@UnsupportedAppUsage
public static final int PROCESS_STATE_TOP = 2;
- /** @hide Process is hosting a foreground service with location type. */
- public static final int PROCESS_STATE_FOREGROUND_SERVICE_LOCATION = 3;
-
/** @hide Process is bound to a TOP app. This is ranked below SERVICE_LOCATION so that
* it doesn't get the capability of location access while-in-use. */
- public static final int PROCESS_STATE_BOUND_TOP = 4;
+ public static final int PROCESS_STATE_BOUND_TOP = 3;
/** @hide Process is hosting a foreground service. */
@UnsupportedAppUsage
- public static final int PROCESS_STATE_FOREGROUND_SERVICE = 5;
+ public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4;
/** @hide Process is hosting a foreground service due to a system binding. */
@UnsupportedAppUsage
- public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 6;
+ public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 5;
/** @hide Process is important to the user, and something they are aware of. */
- public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 7;
+ public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 6;
/** @hide Process is important to the user, but not something they are aware of. */
@UnsupportedAppUsage
- public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 8;
+ public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 7;
/** @hide Process is in the background transient so we will try to keep running. */
- public static final int PROCESS_STATE_TRANSIENT_BACKGROUND = 9;
+ public static final int PROCESS_STATE_TRANSIENT_BACKGROUND = 8;
/** @hide Process is in the background running a backup/restore operation. */
- public static final int PROCESS_STATE_BACKUP = 10;
+ public static final int PROCESS_STATE_BACKUP = 9;
/** @hide Process is in the background running a service. Unlike oom_adj, this level
* is used for both the normal running in background state and the executing
* operations state. */
@UnsupportedAppUsage
- public static final int PROCESS_STATE_SERVICE = 11;
+ public static final int PROCESS_STATE_SERVICE = 10;
/** @hide Process is in the background running a receiver. Note that from the
* perspective of oom_adj, receivers run at a higher foreground level, but for our
* prioritization here that is not necessary and putting them below services means
* many fewer changes in some process states as they receive broadcasts. */
@UnsupportedAppUsage
- public static final int PROCESS_STATE_RECEIVER = 12;
+ public static final int PROCESS_STATE_RECEIVER = 11;
/** @hide Same as {@link #PROCESS_STATE_TOP} but while device is sleeping. */
- public static final int PROCESS_STATE_TOP_SLEEPING = 13;
+ public static final int PROCESS_STATE_TOP_SLEEPING = 12;
/** @hide Process is in the background, but it can't restore its state so we want
* to try to avoid killing it. */
- public static final int PROCESS_STATE_HEAVY_WEIGHT = 14;
+ public static final int PROCESS_STATE_HEAVY_WEIGHT = 13;
/** @hide Process is in the background but hosts the home activity. */
@UnsupportedAppUsage
- public static final int PROCESS_STATE_HOME = 15;
+ public static final int PROCESS_STATE_HOME = 14;
/** @hide Process is in the background but hosts the last shown activity. */
- public static final int PROCESS_STATE_LAST_ACTIVITY = 16;
+ public static final int PROCESS_STATE_LAST_ACTIVITY = 15;
/** @hide Process is being cached for later use and contains activities. */
@UnsupportedAppUsage
- public static final int PROCESS_STATE_CACHED_ACTIVITY = 17;
+ public static final int PROCESS_STATE_CACHED_ACTIVITY = 16;
/** @hide Process is being cached for later use and is a client of another cached
* process that contains activities. */
- public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 18;
+ public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 17;
/** @hide Process is being cached for later use and has an activity that corresponds
* to an existing recent task. */
- public static final int PROCESS_STATE_CACHED_RECENT = 19;
+ public static final int PROCESS_STATE_CACHED_RECENT = 18;
/** @hide Process is being cached for later use and is empty. */
- public static final int PROCESS_STATE_CACHED_EMPTY = 20;
+ public static final int PROCESS_STATE_CACHED_EMPTY = 19;
/** @hide Process does not exist. */
- public static final int PROCESS_STATE_NONEXISTENT = 21;
+ public static final int PROCESS_STATE_NONEXISTENT = 20;
+
+ /**
+ * The set of flags for process capability.
+ * @hide
+ */
+ @IntDef(flag = true, prefix = { "PROCESS_CAPABILITY_" }, value = {
+ PROCESS_CAPABILITY_NONE,
+ PROCESS_CAPABILITY_FOREGROUND_LOCATION,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ProcessCapability {}
+
+ /** @hide Process does not have any capability */
+ @TestApi
+ public static final int PROCESS_CAPABILITY_NONE = 0;
+
+ /** @hide Process can access location while in foreground */
+ @TestApi
+ public static final int PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1 << 0;
+
+ /** @hide all capabilities, the ORing of all flags in {@link ProcessCapability}*/
+ @TestApi
+ public static final int PROCESS_CAPABILITY_ALL = PROCESS_CAPABILITY_FOREGROUND_LOCATION;
// NOTE: If PROCESS_STATEs are added, then new fields must be added
// to frameworks/base/core/proto/android/app/enums.proto and the following method must
@@ -557,7 +603,6 @@
return AppProtoEnums.PROCESS_STATE_TOP;
case PROCESS_STATE_BOUND_TOP:
return AppProtoEnums.PROCESS_STATE_BOUND_TOP;
- case PROCESS_STATE_FOREGROUND_SERVICE_LOCATION:
case PROCESS_STATE_FOREGROUND_SERVICE:
return AppProtoEnums.PROCESS_STATE_FOREGROUND_SERVICE;
case PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
@@ -612,8 +657,7 @@
/** @hide Is this a foreground service type? */
public static boolean isForegroundService(int procState) {
- return procState == PROCESS_STATE_FOREGROUND_SERVICE_LOCATION
- || procState == PROCESS_STATE_FOREGROUND_SERVICE;
+ return procState == PROCESS_STATE_FOREGROUND_SERVICE;
}
/** @hide requestType for assist context: only basic information. */
@@ -2930,7 +2974,7 @@
return IMPORTANCE_PERCEPTIBLE;
} else if (procState >= PROCESS_STATE_IMPORTANT_FOREGROUND) {
return IMPORTANCE_VISIBLE;
- } else if (procState >= PROCESS_STATE_FOREGROUND_SERVICE_LOCATION) {
+ } else if (procState >= PROCESS_STATE_FOREGROUND_SERVICE) {
return IMPORTANCE_FOREGROUND_SERVICE;
} else {
return IMPORTANCE_FOREGROUND;
@@ -4087,7 +4131,7 @@
* Action an app can implement to handle reports from {@link #setWatchHeapLimit(long)}.
* If your package has an activity handling this action, it will be launched with the
* heap data provided to it the same way as {@link Intent#ACTION_SEND}. Note that to
- * match the activty must support this action and a MIME type of "*/*".
+ * match, the activity must support this action and a MIME type of "*/*".
*/
public static final String ACTION_REPORT_HEAP_LIMIT = "android.app.action.REPORT_HEAP_LIMIT";
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 6772884..f91453e 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -1301,8 +1301,8 @@
/**
* Set's whether the activity launched with this option should be a task overlay. That is the
- * activity will always be the top activity of the task. If {@param canResume} is true, then
- * the task will also not be moved to the front of the stack.
+ * activity will always be the top activity of the task.
+ * @param canResume {@code false} if the task will also not be moved to the front of the stack.
* @hide
*/
@TestApi
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 8bca87e6..765c358 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -282,10 +282,14 @@
/**
* Uid state: The UID is running a foreground service of location type.
* The lower the UID state the more important the UID is for the user.
+ * This uid state is a counterpart to PROCESS_STATE_FOREGROUND_SERVICE_LOCATION which has been
+ * deprecated.
* @hide
+ * @deprecated
*/
@TestApi
@SystemApi
+ @Deprecated
public static final int UID_STATE_FOREGROUND_SERVICE_LOCATION = 300;
/**
@@ -298,13 +302,6 @@
public static final int UID_STATE_FOREGROUND_SERVICE = 400;
/**
- * The max, which is min priority, UID state for which any app op
- * would be considered as performed in the foreground.
- * @hide
- */
- public static final int UID_STATE_MAX_LAST_NON_RESTRICTED = UID_STATE_FOREGROUND_SERVICE;
-
- /**
* Uid state: The UID is a foreground app. The lower the UID
* state the more important the UID is for the user.
* @hide
@@ -314,6 +311,13 @@
public static final int UID_STATE_FOREGROUND = 500;
/**
+ * The max, which is min priority, UID state for which any app op
+ * would be considered as performed in the foreground.
+ * @hide
+ */
+ public static final int UID_STATE_MAX_LAST_NON_RESTRICTED = UID_STATE_FOREGROUND;
+
+ /**
* Uid state: The UID is a background app. The lower the UID
* state the more important the UID is for the user.
* @hide
@@ -344,47 +348,25 @@
public static final int MIN_PRIORITY_UID_STATE = UID_STATE_CACHED;
/**
- * Resolves the first unrestricted state given an app op. Location is
- * special as we want to allow its access only if a dedicated location
- * foreground service is running. For other ops we consider any foreground
- * service as a foreground state.
- *
+ * Resolves the first unrestricted state given an app op.
* @param op The op to resolve.
* @return The last restricted UID state.
*
* @hide
*/
public static int resolveFirstUnrestrictedUidState(int op) {
- switch (op) {
- case OP_FINE_LOCATION:
- case OP_COARSE_LOCATION:
- case OP_MONITOR_LOCATION:
- case OP_MONITOR_HIGH_POWER_LOCATION: {
- return UID_STATE_FOREGROUND_SERVICE_LOCATION;
- }
- }
- return UID_STATE_FOREGROUND_SERVICE;
+ return UID_STATE_FOREGROUND;
}
/**
- * Resolves the last restricted state given an app op. Location is
- * special as we want to allow its access only if a dedicated location
- * foreground service is running. For other ops we consider any foreground
- * service as a foreground state.
- *
+ * Resolves the last restricted state given an app op.
* @param op The op to resolve.
* @return The last restricted UID state.
*
* @hide
*/
public static int resolveLastRestrictedUidState(int op) {
- switch (op) {
- case OP_FINE_LOCATION:
- case OP_COARSE_LOCATION: {
- return UID_STATE_FOREGROUND_SERVICE;
- }
- }
- return UID_STATE_FOREGROUND;
+ return UID_STATE_BACKGROUND;
}
/** @hide Note: Keep these sorted */
@@ -4603,7 +4585,6 @@
*
* @param fromUidState The UID state from which to query. Could be one of
* {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
- * {@link #UID_STATE_FOREGROUND_SERVICE_LOCATION},
* {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
* {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
* @param toUidState The UID state to which to query.
@@ -4664,7 +4645,6 @@
*
* @param fromUidState The UID state from which to query. Could be one of
* {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
- * {@link #UID_STATE_FOREGROUND_SERVICE_LOCATION},
* {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
* {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
* @param toUidState The UID state to which to query.
@@ -4728,7 +4708,6 @@
*
* @param fromUidState The UID state from which to query. Could be one of
* {@link #UID_STATE_PERSISTENT}, {@link #UID_STATE_TOP},
- * {@link #UID_STATE_FOREGROUND_SERVICE_LOCATION},
* {@link #UID_STATE_FOREGROUND_SERVICE}, {@link #UID_STATE_FOREGROUND},
* {@link #UID_STATE_BACKGROUND}, {@link #UID_STATE_CACHED}.
* @param toUidState The UID state from which to query.
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index eb2b2bc..466c1a96 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -73,6 +73,7 @@
import android.system.Os;
import android.system.OsConstants;
import android.system.StructStat;
+import android.text.TextUtils;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
import android.util.Log;
@@ -1341,6 +1342,19 @@
}
@Override
+ public void sendOrderedBroadcast(Intent intent, String receiverPermission,
+ String receiverAppOp, BroadcastReceiver resultReceiver, Handler scheduler,
+ int initialCode, String initialData, @Nullable Bundle initialExtras) {
+ int intAppOp = AppOpsManager.OP_NONE;
+ if (!TextUtils.isEmpty(receiverAppOp)) {
+ intAppOp = AppOpsManager.strOpToOp(receiverAppOp);
+ }
+ sendOrderedBroadcastAsUser(intent, getUser(),
+ receiverPermission, intAppOp, resultReceiver, scheduler, initialCode, initialData,
+ initialExtras);
+ }
+
+ @Override
@Deprecated
public void sendStickyBroadcast(Intent intent) {
warnIfCallingFromSystemProcess();
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index f591441..770e5f7 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -70,6 +70,7 @@
import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationDefinition;
import android.view.RemoteAnimationAdapter;
+import android.view.WindowContainerTransaction;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.os.IResultReceiver;
import com.android.internal.policy.IKeyguardDismissCallback;
@@ -220,6 +221,7 @@
void setTaskResizeable(int taskId, int resizeableMode);
void toggleFreeformWindowingMode(in IBinder token);
void resizeTask(int taskId, in Rect bounds, int resizeMode);
+ void applyContainerTransaction(in WindowContainerTransaction t);
void moveStackToDisplay(int stackId, int displayId);
void removeStack(int stackId);
diff --git a/core/java/android/app/IUidObserver.aidl b/core/java/android/app/IUidObserver.aidl
index e116d98..7713e25 100644
--- a/core/java/android/app/IUidObserver.aidl
+++ b/core/java/android/app/IUidObserver.aidl
@@ -50,8 +50,9 @@
* @param procState The updated process state for the uid.
* @param procStateSeq The sequence no. associated with process state change of the uid,
* see UidRecord.procStateSeq for details.
+ * @param capability the updated process capability for the uid.
*/
- void onUidStateChanged(int uid, int procState, long procStateSeq);
+ void onUidStateChanged(int uid, int procState, long procStateSeq, int capability);
// =============== End of transactions used on native side as well ============================
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index efb9f6bb..47118a8 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -17,7 +17,6 @@
package android.app;
import static android.annotation.Dimension.DP;
-import static android.graphics.drawable.Icon.TYPE_BITMAP;
import static com.android.internal.util.ContrastColorUtil.satisfiesTextContrast;
@@ -8741,26 +8740,20 @@
* If your app produces multiple bubbles, the image should be unique for each of them.
* </p>
*
- * <p>The shape of a bubble icon is adaptive and can match the device theme.
+ * <p>The shape of a bubble icon is adaptive and will match the device theme.
*
- * If your icon is bitmap-based, you should create it using
- * {@link Icon#createWithAdaptiveBitmap(Bitmap)}, otherwise this method will throw.
- *
- * If your icon is not bitmap-based, you should expect that the icon will be tinted.
+ * Ideally your icon should be constructed via
+ * {@link Icon#createWithAdaptiveBitmap(Bitmap)}, otherwise, the icon will be shrunk
+ * and placed on an adaptive shape.
* </p>
*
- * @throws IllegalArgumentException if icon is null or a non-adaptive bitmap
+ * @throws IllegalArgumentException if icon is null.
*/
@NonNull
public BubbleMetadata.Builder setIcon(@NonNull Icon icon) {
if (icon == null) {
throw new IllegalArgumentException("Bubbles require non-null icon");
}
- if (icon.getType() == TYPE_BITMAP) {
- throw new IllegalArgumentException("When using bitmap based icons, Bubbles "
- + "require TYPE_ADAPTIVE_BITMAP, please use"
- + " Icon#createWithAdaptiveBitmap instead");
- }
mIcon = icon;
return this;
}
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 4b4a071..06b9506 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -94,6 +94,12 @@
* {@link #FLAG_CANCEL_CURRENT} or {@link #FLAG_UPDATE_CURRENT} to either
* cancel or modify whatever current PendingIntent is associated with the
* Intent you are supplying.
+ *
+ * <p>Also note that flags like {@link #FLAG_ONE_SHOT} or {@link #FLAG_IMMUTABLE} describe the
+ * PendingIntent instance and thus, are used to identify it. Any calls to retrieve or modify a
+ * PendingIntent created with these flags will also require these flags to be supplied in
+ * conjunction with others. E.g. To retrieve an existing PendingIntent created with
+ * FLAG_ONE_SHOT, <b>both</b> FLAG_ONE_SHOT and FLAG_NO_CREATE need to be supplied.
*/
public final class PendingIntent implements Parcelable {
private final IIntentSender mTarget;
@@ -1268,7 +1274,12 @@
return b != null ? new PendingIntent(b, in.getClassCookie(PendingIntent.class)) : null;
}
- /*package*/ PendingIntent(IIntentSender target) {
+ /**
+ * Creates a PendingIntent with the given target.
+ * @param target the backing IIntentSender
+ * @hide
+ */
+ public PendingIntent(IIntentSender target) {
mTarget = target;
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 6a13499..629c2bb 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -23,6 +23,7 @@
import android.app.admin.IDevicePolicyManager;
import android.app.contentsuggestions.ContentSuggestionsManager;
import android.app.contentsuggestions.IContentSuggestionsManager;
+import android.app.job.JobSchedulerFrameworkInitializer;
import android.app.prediction.AppPredictionManager;
import android.app.role.RoleControllerManager;
import android.app.role.RoleManager;
@@ -153,7 +154,6 @@
import android.os.image.DynamicSystemManager;
import android.os.image.IDynamicSystemService;
import android.os.storage.StorageManager;
-import android.telephony.TelephonyRegistryManager;
import android.permission.PermissionControllerManager;
import android.permission.PermissionManager;
import android.print.IPrintManager;
@@ -167,6 +167,7 @@
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
import android.telephony.euicc.EuiccCardManager;
import android.telephony.euicc.EuiccManager;
import android.telephony.ims.RcsMessageManager;
@@ -1298,6 +1299,9 @@
IBatteryStats.Stub.asInterface(b));
}});
//CHECKSTYLE:ON IndentationCheck
+
+ JobSchedulerFrameworkInitializer.initialize();
+ DeviceIdleFrameworkInitializer.initialize();
}
/**
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index c400316..f4c6b50 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -440,6 +440,34 @@
}
/**
+ * Copies the fields specified by mask from delta into this Configuration object.
+ * @hide
+ */
+ public void setTo(@NonNull WindowConfiguration delta, @WindowConfig int mask) {
+ if ((mask & WINDOW_CONFIG_BOUNDS) != 0) {
+ setBounds(delta.mBounds);
+ }
+ if ((mask & WINDOW_CONFIG_APP_BOUNDS) != 0) {
+ setAppBounds(delta.mAppBounds);
+ }
+ if ((mask & WINDOW_CONFIG_WINDOWING_MODE) != 0) {
+ setWindowingMode(delta.mWindowingMode);
+ }
+ if ((mask & WINDOW_CONFIG_ACTIVITY_TYPE) != 0) {
+ setActivityType(delta.mActivityType);
+ }
+ if ((mask & WINDOW_CONFIG_ALWAYS_ON_TOP) != 0) {
+ setAlwaysOnTop(delta.mAlwaysOnTop);
+ }
+ if ((mask & WINDOW_CONFIG_ROTATION) != 0) {
+ setRotation(delta.mRotation);
+ }
+ if ((mask & WINDOW_CONFIG_DISPLAY_WINDOWING_MODE) != 0) {
+ setDisplayWindowingMode(delta.mDisplayWindowingMode);
+ }
+ }
+
+ /**
* Return a bit mask of the differences between this Configuration object and the given one.
* Does not change the values of either. Any undefined fields in <var>other</var> are ignored.
* @param other The configuration to diff against.
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 7de8793..17f1a07 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -53,6 +53,7 @@
import android.os.storage.StorageManager;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Pair;
import com.android.internal.annotations.VisibleForTesting;
@@ -136,7 +137,7 @@
private boolean mNoPerms;
private boolean mSingleUser;
- private ThreadLocal<String> mCallingPackage;
+ private ThreadLocal<Pair<String, String>> mCallingPackage;
private Transport mTransport = new Transport();
@@ -226,11 +227,13 @@
}
@Override
- public Cursor query(String callingPkg, Uri uri, @Nullable String[] projection,
- @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) {
+ public Cursor query(String callingPkg, @Nullable String featureId, Uri uri,
+ @Nullable String[] projection, @Nullable Bundle queryArgs,
+ @Nullable ICancellationSignal cancellationSignal) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceReadPermission(callingPkg, featureId, uri, null)
+ != AppOpsManager.MODE_ALLOWED) {
// The caller has no access to the data, so return an empty cursor with
// the columns in the requested order. The caller may ask for an invalid
// column and we would not catch that but this is not a problem in practice.
@@ -246,7 +249,8 @@
// we have to execute the query as if allowed to get a cursor with the
// columns. We then use the column names to return an empty cursor.
Cursor cursor;
- final String original = setCallingPackage(callingPkg);
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
cursor = mInterface.query(
uri, projection, queryArgs,
@@ -264,7 +268,8 @@
return new MatrixCursor(cursor.getColumnNames(), 0);
}
Trace.traceBegin(TRACE_TAG_DATABASE, "query");
- final String original = setCallingPackage(callingPkg);
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
return mInterface.query(
uri, projection, queryArgs,
@@ -293,12 +298,15 @@
}
@Override
- public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) {
+ public Uri insert(String callingPkg, @Nullable String featureId, Uri uri,
+ ContentValues initialValues) {
uri = validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
- final String original = setCallingPackage(callingPkg);
+ if (enforceWritePermission(callingPkg, featureId, uri, null)
+ != AppOpsManager.MODE_ALLOWED) {
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
return rejectInsert(uri, initialValues);
} finally {
@@ -306,7 +314,8 @@
}
}
Trace.traceBegin(TRACE_TAG_DATABASE, "insert");
- final String original = setCallingPackage(callingPkg);
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
return maybeAddUserId(mInterface.insert(uri, initialValues), userId);
} catch (RemoteException e) {
@@ -318,14 +327,17 @@
}
@Override
- public int bulkInsert(String callingPkg, Uri uri, ContentValues[] initialValues) {
+ public int bulkInsert(String callingPkg, @Nullable String featureId, Uri uri,
+ ContentValues[] initialValues) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceWritePermission(callingPkg, featureId, uri, null)
+ != AppOpsManager.MODE_ALLOWED) {
return 0;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "bulkInsert");
- final String original = setCallingPackage(callingPkg);
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
return mInterface.bulkInsert(uri, initialValues);
} catch (RemoteException e) {
@@ -337,8 +349,8 @@
}
@Override
- public ContentProviderResult[] applyBatch(String callingPkg, String authority,
- ArrayList<ContentProviderOperation> operations)
+ public ContentProviderResult[] applyBatch(String callingPkg, @Nullable String featureId,
+ String authority, ArrayList<ContentProviderOperation> operations)
throws OperationApplicationException {
validateIncomingAuthority(authority);
int numOperations = operations.size();
@@ -355,20 +367,21 @@
operations.set(i, operation);
}
if (operation.isReadOperation()) {
- if (enforceReadPermission(callingPkg, uri, null)
+ if (enforceReadPermission(callingPkg, featureId, uri, null)
!= AppOpsManager.MODE_ALLOWED) {
throw new OperationApplicationException("App op not allowed", 0);
}
}
if (operation.isWriteOperation()) {
- if (enforceWritePermission(callingPkg, uri, null)
+ if (enforceWritePermission(callingPkg, featureId, uri, null)
!= AppOpsManager.MODE_ALLOWED) {
throw new OperationApplicationException("App op not allowed", 0);
}
}
}
Trace.traceBegin(TRACE_TAG_DATABASE, "applyBatch");
- final String original = setCallingPackage(callingPkg);
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
ContentProviderResult[] results = mInterface.applyBatch(authority,
operations);
@@ -390,14 +403,17 @@
}
@Override
- public int delete(String callingPkg, Uri uri, String selection, String[] selectionArgs) {
+ public int delete(String callingPkg, @Nullable String featureId, Uri uri, String selection,
+ String[] selectionArgs) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceWritePermission(callingPkg, featureId, uri, null)
+ != AppOpsManager.MODE_ALLOWED) {
return 0;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "delete");
- final String original = setCallingPackage(callingPkg);
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
return mInterface.delete(uri, selection, selectionArgs);
} catch (RemoteException e) {
@@ -409,15 +425,17 @@
}
@Override
- public int update(String callingPkg, Uri uri, ContentValues values, String selection,
- String[] selectionArgs) {
+ public int update(String callingPkg, @Nullable String featureId, Uri uri,
+ ContentValues values, String selection, String[] selectionArgs) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- if (enforceWritePermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceWritePermission(callingPkg, featureId, uri, null)
+ != AppOpsManager.MODE_ALLOWED) {
return 0;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "update");
- final String original = setCallingPackage(callingPkg);
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
return mInterface.update(uri, values, selection, selectionArgs);
} catch (RemoteException e) {
@@ -429,14 +447,15 @@
}
@Override
- public ParcelFileDescriptor openFile(
- String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal,
- IBinder callerToken) throws FileNotFoundException {
+ public ParcelFileDescriptor openFile(String callingPkg, @Nullable String featureId,
+ Uri uri, String mode, ICancellationSignal cancellationSignal, IBinder callerToken)
+ throws FileNotFoundException {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- enforceFilePermission(callingPkg, uri, mode, callerToken);
+ enforceFilePermission(callingPkg, featureId, uri, mode, callerToken);
Trace.traceBegin(TRACE_TAG_DATABASE, "openFile");
- final String original = setCallingPackage(callingPkg);
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
return mInterface.openFile(
uri, mode, CancellationSignal.fromTransport(cancellationSignal));
@@ -449,14 +468,15 @@
}
@Override
- public AssetFileDescriptor openAssetFile(
- String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
+ public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String featureId,
+ Uri uri, String mode, ICancellationSignal cancellationSignal)
throws FileNotFoundException {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- enforceFilePermission(callingPkg, uri, mode, null);
+ enforceFilePermission(callingPkg, featureId, uri, mode, null);
Trace.traceBegin(TRACE_TAG_DATABASE, "openAssetFile");
- final String original = setCallingPackage(callingPkg);
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
return mInterface.openAssetFile(
uri, mode, CancellationSignal.fromTransport(cancellationSignal));
@@ -469,12 +489,13 @@
}
@Override
- public Bundle call(String callingPkg, String authority, String method, @Nullable String arg,
- @Nullable Bundle extras) {
+ public Bundle call(String callingPkg, @Nullable String featureId, String authority,
+ String method, @Nullable String arg, @Nullable Bundle extras) {
validateIncomingAuthority(authority);
Bundle.setDefusable(extras, true);
Trace.traceBegin(TRACE_TAG_DATABASE, "call");
- final String original = setCallingPackage(callingPkg);
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
return mInterface.call(authority, method, arg, extras);
} catch (RemoteException e) {
@@ -501,14 +522,16 @@
}
@Override
- public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType,
- Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
+ public AssetFileDescriptor openTypedAssetFile(String callingPkg,
+ @Nullable String featureId, Uri uri, String mimeType, Bundle opts,
+ ICancellationSignal cancellationSignal) throws FileNotFoundException {
Bundle.setDefusable(opts, true);
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
- enforceFilePermission(callingPkg, uri, "r", null);
+ enforceFilePermission(callingPkg, featureId, uri, "r", null);
Trace.traceBegin(TRACE_TAG_DATABASE, "openTypedAssetFile");
- final String original = setCallingPackage(callingPkg);
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
return mInterface.openTypedAssetFile(
uri, mimeType, opts, CancellationSignal.fromTransport(cancellationSignal));
@@ -526,15 +549,17 @@
}
@Override
- public Uri canonicalize(String callingPkg, Uri uri) {
+ public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri) {
uri = validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceReadPermission(callingPkg, featureId, uri, null)
+ != AppOpsManager.MODE_ALLOWED) {
return null;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "canonicalize");
- final String original = setCallingPackage(callingPkg);
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
return maybeAddUserId(mInterface.canonicalize(uri), userId);
} catch (RemoteException e) {
@@ -546,15 +571,17 @@
}
@Override
- public Uri uncanonicalize(String callingPkg, Uri uri) {
+ public Uri uncanonicalize(String callingPkg, String featureId, Uri uri) {
uri = validateIncomingUri(uri);
int userId = getUserIdFromUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceReadPermission(callingPkg, featureId, uri, null)
+ != AppOpsManager.MODE_ALLOWED) {
return null;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "uncanonicalize");
- final String original = setCallingPackage(callingPkg);
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
return maybeAddUserId(mInterface.uncanonicalize(uri), userId);
} catch (RemoteException e) {
@@ -566,15 +593,17 @@
}
@Override
- public boolean refresh(String callingPkg, Uri uri, Bundle args,
+ public boolean refresh(String callingPkg, String featureId, Uri uri, Bundle args,
ICancellationSignal cancellationSignal) throws RemoteException {
uri = validateIncomingUri(uri);
uri = getUriWithoutUserId(uri);
- if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
+ if (enforceReadPermission(callingPkg, featureId, uri, null)
+ != AppOpsManager.MODE_ALLOWED) {
return false;
}
Trace.traceBegin(TRACE_TAG_DATABASE, "refresh");
- final String original = setCallingPackage(callingPkg);
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
return mInterface.refresh(uri, args,
CancellationSignal.fromTransport(cancellationSignal));
@@ -585,11 +614,13 @@
}
@Override
- public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags) {
+ public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri,
+ int uid, int modeFlags) {
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
Trace.traceBegin(TRACE_TAG_DATABASE, "checkUriPermission");
- final String original = setCallingPackage(callingPkg);
+ final Pair<String, String> original = setCallingPackage(
+ new Pair<>(callingPkg, featureId));
try {
return mInterface.checkUriPermission(uri, uid, modeFlags);
} catch (RemoteException e) {
@@ -600,44 +631,47 @@
}
}
- private void enforceFilePermission(String callingPkg, Uri uri, String mode,
- IBinder callerToken) throws FileNotFoundException, SecurityException {
+ private void enforceFilePermission(String callingPkg, @Nullable String featureId, Uri uri,
+ String mode, IBinder callerToken) throws FileNotFoundException, SecurityException {
if (mode != null && mode.indexOf('w') != -1) {
- if (enforceWritePermission(callingPkg, uri, callerToken)
+ if (enforceWritePermission(callingPkg, featureId, uri, callerToken)
!= AppOpsManager.MODE_ALLOWED) {
throw new FileNotFoundException("App op not allowed");
}
} else {
- if (enforceReadPermission(callingPkg, uri, callerToken)
+ if (enforceReadPermission(callingPkg, featureId, uri, callerToken)
!= AppOpsManager.MODE_ALLOWED) {
throw new FileNotFoundException("App op not allowed");
}
}
}
- private int enforceReadPermission(String callingPkg, Uri uri, IBinder callerToken)
+ private int enforceReadPermission(String callingPkg, @Nullable String featureId, Uri uri,
+ IBinder callerToken)
throws SecurityException {
- final int mode = enforceReadPermissionInner(uri, callingPkg, callerToken);
+ final int mode = enforceReadPermissionInner(uri, callingPkg, featureId, callerToken);
if (mode != MODE_ALLOWED) {
return mode;
}
- return noteProxyOp(callingPkg, mReadOp);
+ return noteProxyOp(callingPkg, featureId, mReadOp);
}
- private int enforceWritePermission(String callingPkg, Uri uri, IBinder callerToken)
+ private int enforceWritePermission(String callingPkg, String featureId, Uri uri,
+ IBinder callerToken)
throws SecurityException {
- final int mode = enforceWritePermissionInner(uri, callingPkg, callerToken);
+ final int mode = enforceWritePermissionInner(uri, callingPkg, featureId, callerToken);
if (mode != MODE_ALLOWED) {
return mode;
}
- return noteProxyOp(callingPkg, mWriteOp);
+ return noteProxyOp(callingPkg, featureId, mWriteOp);
}
- private int noteProxyOp(String callingPkg, int op) {
+ private int noteProxyOp(String callingPkg, String featureId, int op) {
if (op != AppOpsManager.OP_NONE) {
- int mode = mAppOpsManager.noteProxyOp(op, callingPkg);
+ int mode = mAppOpsManager.noteProxyOp(op, callingPkg, Binder.getCallingUid(),
+ featureId, null);
return mode == MODE_DEFAULT ? MODE_IGNORED : mode;
}
@@ -659,18 +693,19 @@
* associated with that permission.
*/
private int checkPermissionAndAppOp(String permission, String callingPkg,
- IBinder callerToken) {
+ @Nullable String featureId, IBinder callerToken) {
if (getContext().checkPermission(permission, Binder.getCallingPid(), Binder.getCallingUid(),
callerToken) != PERMISSION_GRANTED) {
return MODE_ERRORED;
}
- return mTransport.noteProxyOp(callingPkg, AppOpsManager.permissionToOpCode(permission));
+ return mTransport.noteProxyOp(callingPkg, featureId,
+ AppOpsManager.permissionToOpCode(permission));
}
/** {@hide} */
- protected int enforceReadPermissionInner(Uri uri, String callingPkg, IBinder callerToken)
- throws SecurityException {
+ protected int enforceReadPermissionInner(Uri uri, String callingPkg,
+ @Nullable String featureId, IBinder callerToken) throws SecurityException {
final Context context = getContext();
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
@@ -684,7 +719,8 @@
if (mExported && checkUser(pid, uid, context)) {
final String componentPerm = getReadPermission();
if (componentPerm != null) {
- final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, callerToken);
+ final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, featureId,
+ callerToken);
if (mode == MODE_ALLOWED) {
return MODE_ALLOWED;
} else {
@@ -703,7 +739,8 @@
for (PathPermission pp : pps) {
final String pathPerm = pp.getReadPermission();
if (pathPerm != null && pp.match(path)) {
- final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, callerToken);
+ final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, featureId,
+ callerToken);
if (mode == MODE_ALLOWED) {
return MODE_ALLOWED;
} else {
@@ -751,8 +788,8 @@
}
/** {@hide} */
- protected int enforceWritePermissionInner(Uri uri, String callingPkg, IBinder callerToken)
- throws SecurityException {
+ protected int enforceWritePermissionInner(Uri uri, String callingPkg,
+ @Nullable String featureId, IBinder callerToken) throws SecurityException {
final Context context = getContext();
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
@@ -766,7 +803,8 @@
if (mExported && checkUser(pid, uid, context)) {
final String componentPerm = getWritePermission();
if (componentPerm != null) {
- final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, callerToken);
+ final int mode = checkPermissionAndAppOp(componentPerm, callingPkg, featureId,
+ callerToken);
if (mode == MODE_ALLOWED) {
return MODE_ALLOWED;
} else {
@@ -785,7 +823,8 @@
for (PathPermission pp : pps) {
final String pathPerm = pp.getWritePermission();
if (pathPerm != null && pp.match(path)) {
- final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, callerToken);
+ final int mode = checkPermissionAndAppOp(pathPerm, callingPkg, featureId,
+ callerToken);
if (mode == MODE_ALLOWED) {
return MODE_ALLOWED;
} else {
@@ -851,11 +890,11 @@
}
/**
- * Set the calling package, returning the current value (or {@code null})
+ * Set the calling package/feature, returning the current value (or {@code null})
* which can be used later to restore the previous state.
*/
- private String setCallingPackage(String callingPackage) {
- final String original = mCallingPackage.get();
+ private Pair<String, String> setCallingPackage(Pair<String, String> callingPackage) {
+ final Pair<String, String> original = mCallingPackage.get();
mCallingPackage.set(callingPackage);
onCallingPackageChanged();
return original;
@@ -876,16 +915,42 @@
* calling UID.
*/
public final @Nullable String getCallingPackage() {
- final String pkg = mCallingPackage.get();
+ final Pair<String, String> pkg = mCallingPackage.get();
if (pkg != null) {
- mTransport.mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg);
+ mTransport.mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg.first);
+ return pkg.first;
}
- return pkg;
+
+ return null;
+ }
+
+ /**
+ * Return the feature in the package of the caller that initiated the request being
+ * processed on the current thread. Returns {@code null} if not currently processing
+ * a request of the request is for the default feature.
+ * <p>
+ * This will always return {@code null} when processing
+ * {@link #getType(Uri)} or {@link #getStreamTypes(Uri, String)} requests.
+ *
+ * @see #getCallingPackage
+ */
+ public final @Nullable String getCallingFeatureId() {
+ final Pair<String, String> pkg = mCallingPackage.get();
+ if (pkg != null) {
+ return pkg.second;
+ }
+
+ return null;
}
/** {@hide} */
public final @Nullable String getCallingPackageUnchecked() {
- return mCallingPackage.get();
+ final Pair<String, String> pkg = mCallingPackage.get();
+ if (pkg != null) {
+ return pkg.first;
+ }
+
+ return null;
}
/** {@hide} */
@@ -899,10 +964,10 @@
/** {@hide} */
public final long binderToken;
/** {@hide} */
- public final String callingPackage;
+ public final Pair<String, String> callingPackage;
/** {@hide} */
- public CallingIdentity(long binderToken, String callingPackage) {
+ public CallingIdentity(long binderToken, Pair<String, String> callingPackage) {
this.binderToken = binderToken;
this.callingPackage = callingPackage;
}
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index 8a4330e..d2632e7 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -80,6 +80,7 @@
private final IContentProvider mContentProvider;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final String mPackageName;
+ private final @Nullable String mFeatureId;
private final String mAuthority;
private final boolean mStable;
@@ -103,6 +104,7 @@
mContentResolver = contentResolver;
mContentProvider = contentProvider;
mPackageName = contentResolver.mPackageName;
+ mFeatureId = contentResolver.mFeatureId;
mAuthority = authority;
mStable = stable;
@@ -193,7 +195,7 @@
cancellationSignal.setRemote(remoteCancellationSignal);
}
final Cursor cursor = mContentProvider.query(
- mPackageName, uri, projection, queryArgs, remoteCancellationSignal);
+ mPackageName, mFeatureId, uri, projection, queryArgs, remoteCancellationSignal);
if (cursor == null) {
return null;
}
@@ -253,7 +255,7 @@
beforeRemote();
try {
- return mContentProvider.canonicalize(mPackageName, url);
+ return mContentProvider.canonicalize(mPackageName, mFeatureId, url);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -271,7 +273,7 @@
beforeRemote();
try {
- return mContentProvider.uncanonicalize(mPackageName, url);
+ return mContentProvider.uncanonicalize(mPackageName, mFeatureId, url);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -296,7 +298,8 @@
remoteCancellationSignal = mContentProvider.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
- return mContentProvider.refresh(mPackageName, url, args, remoteCancellationSignal);
+ return mContentProvider.refresh(mPackageName, mFeatureId, url, args,
+ remoteCancellationSignal);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -315,7 +318,8 @@
beforeRemote();
try {
- return mContentProvider.checkUriPermission(mPackageName, uri, uid, modeFlags);
+ return mContentProvider.checkUriPermission(mPackageName, mFeatureId, uri, uid,
+ modeFlags);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -334,7 +338,7 @@
beforeRemote();
try {
- return mContentProvider.insert(mPackageName, url, initialValues);
+ return mContentProvider.insert(mPackageName, mFeatureId, url, initialValues);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -354,7 +358,7 @@
beforeRemote();
try {
- return mContentProvider.bulkInsert(mPackageName, url, initialValues);
+ return mContentProvider.bulkInsert(mPackageName, mFeatureId, url, initialValues);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -373,7 +377,8 @@
beforeRemote();
try {
- return mContentProvider.delete(mPackageName, url, selection, selectionArgs);
+ return mContentProvider.delete(mPackageName, mFeatureId, url, selection,
+ selectionArgs);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -392,7 +397,8 @@
beforeRemote();
try {
- return mContentProvider.update(mPackageName, url, values, selection, selectionArgs);
+ return mContentProvider.update(mPackageName, mFeatureId, url, values, selection,
+ selectionArgs);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -436,7 +442,8 @@
remoteSignal = mContentProvider.createCancellationSignal();
signal.setRemote(remoteSignal);
}
- return mContentProvider.openFile(mPackageName, url, mode, remoteSignal, null);
+ return mContentProvider.openFile(mPackageName, mFeatureId, url, mode, remoteSignal,
+ null);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -480,7 +487,8 @@
remoteSignal = mContentProvider.createCancellationSignal();
signal.setRemote(remoteSignal);
}
- return mContentProvider.openAssetFile(mPackageName, url, mode, remoteSignal);
+ return mContentProvider.openAssetFile(mPackageName, mFeatureId, url, mode,
+ remoteSignal);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -521,7 +529,7 @@
signal.setRemote(remoteSignal);
}
return mContentProvider.openTypedAssetFile(
- mPackageName, uri, mimeTypeFilter, opts, remoteSignal);
+ mPackageName, mFeatureId, uri, mimeTypeFilter, opts, remoteSignal);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -548,7 +556,7 @@
beforeRemote();
try {
- return mContentProvider.applyBatch(mPackageName, authority, operations);
+ return mContentProvider.applyBatch(mPackageName, mFeatureId, authority, operations);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
@@ -574,7 +582,7 @@
beforeRemote();
try {
- return mContentProvider.call(mPackageName, authority, method, arg, extras);
+ return mContentProvider.call(mPackageName, mFeatureId, authority, method, arg, extras);
} catch (DeadObjectException e) {
if (!mStable) {
mContentResolver.unstableProviderDied(mContentProvider);
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index cd735d4..f082690 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -83,6 +83,7 @@
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
+ String callingFeatureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
// String[] projection
@@ -101,7 +102,8 @@
ICancellationSignal cancellationSignal = ICancellationSignal.Stub.asInterface(
data.readStrongBinder());
- Cursor cursor = query(callingPkg, url, projection, queryArgs, cancellationSignal);
+ Cursor cursor = query(callingPkg, callingFeatureId, url, projection, queryArgs,
+ cancellationSignal);
if (cursor != null) {
CursorToBulkCursorAdaptor adaptor = null;
@@ -148,10 +150,11 @@
{
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
+ String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
ContentValues values = ContentValues.CREATOR.createFromParcel(data);
- Uri out = insert(callingPkg, url, values);
+ Uri out = insert(callingPkg, featureId, url, values);
reply.writeNoException();
Uri.writeToParcel(reply, out);
return true;
@@ -161,10 +164,11 @@
{
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
+ String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
ContentValues[] values = data.createTypedArray(ContentValues.CREATOR);
- int count = bulkInsert(callingPkg, url, values);
+ int count = bulkInsert(callingPkg, featureId, url, values);
reply.writeNoException();
reply.writeInt(count);
return true;
@@ -174,6 +178,7 @@
{
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
+ String featureId = data.readString();
String authority = data.readString();
final int numOperations = data.readInt();
final ArrayList<ContentProviderOperation> operations =
@@ -181,8 +186,8 @@
for (int i = 0; i < numOperations; i++) {
operations.add(i, ContentProviderOperation.CREATOR.createFromParcel(data));
}
- final ContentProviderResult[] results = applyBatch(callingPkg, authority,
- operations);
+ final ContentProviderResult[] results = applyBatch(callingPkg, featureId,
+ authority, operations);
reply.writeNoException();
reply.writeTypedArray(results, 0);
return true;
@@ -192,11 +197,12 @@
{
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
+ String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
String selection = data.readString();
String[] selectionArgs = data.readStringArray();
- int count = delete(callingPkg, url, selection, selectionArgs);
+ int count = delete(callingPkg, featureId, url, selection, selectionArgs);
reply.writeNoException();
reply.writeInt(count);
@@ -207,12 +213,14 @@
{
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
+ String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
ContentValues values = ContentValues.CREATOR.createFromParcel(data);
String selection = data.readString();
String[] selectionArgs = data.readStringArray();
- int count = update(callingPkg, url, values, selection, selectionArgs);
+ int count = update(callingPkg, featureId, url, values, selection,
+ selectionArgs);
reply.writeNoException();
reply.writeInt(count);
@@ -223,6 +231,7 @@
{
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
+ String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
String mode = data.readString();
ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
@@ -230,7 +239,7 @@
IBinder callerToken = data.readStrongBinder();
ParcelFileDescriptor fd;
- fd = openFile(callingPkg, url, mode, signal, callerToken);
+ fd = openFile(callingPkg, featureId, url, mode, signal, callerToken);
reply.writeNoException();
if (fd != null) {
reply.writeInt(1);
@@ -246,13 +255,14 @@
{
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
+ String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
String mode = data.readString();
ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
data.readStrongBinder());
AssetFileDescriptor fd;
- fd = openAssetFile(callingPkg, url, mode, signal);
+ fd = openAssetFile(callingPkg, featureId, url, mode, signal);
reply.writeNoException();
if (fd != null) {
reply.writeInt(1);
@@ -269,12 +279,14 @@
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
+ String featureId = data.readString();
String authority = data.readString();
String method = data.readString();
String stringArg = data.readString();
Bundle args = data.readBundle();
- Bundle responseBundle = call(callingPkg, authority, method, stringArg, args);
+ Bundle responseBundle = call(callingPkg, featureId, authority, method,
+ stringArg, args);
reply.writeNoException();
reply.writeBundle(responseBundle);
@@ -297,6 +309,7 @@
{
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
+ String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
String mimeType = data.readString();
Bundle opts = data.readBundle();
@@ -304,7 +317,7 @@
data.readStrongBinder());
AssetFileDescriptor fd;
- fd = openTypedAssetFile(callingPkg, url, mimeType, opts, signal);
+ fd = openTypedAssetFile(callingPkg, featureId, url, mimeType, opts, signal);
reply.writeNoException();
if (fd != null) {
reply.writeInt(1);
@@ -330,9 +343,10 @@
{
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
+ String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
- Uri out = canonicalize(callingPkg, url);
+ Uri out = canonicalize(callingPkg, featureId, url);
reply.writeNoException();
Uri.writeToParcel(reply, out);
return true;
@@ -342,9 +356,10 @@
{
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
+ String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
- Uri out = uncanonicalize(callingPkg, url);
+ Uri out = uncanonicalize(callingPkg, featureId, url);
reply.writeNoException();
Uri.writeToParcel(reply, out);
return true;
@@ -353,12 +368,13 @@
case REFRESH_TRANSACTION: {
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
+ String featureId = data.readString();
Uri url = Uri.CREATOR.createFromParcel(data);
Bundle args = data.readBundle();
ICancellationSignal signal = ICancellationSignal.Stub.asInterface(
data.readStrongBinder());
- boolean out = refresh(callingPkg, url, args, signal);
+ boolean out = refresh(callingPkg, featureId, url, args, signal);
reply.writeNoException();
reply.writeInt(out ? 0 : -1);
return true;
@@ -367,11 +383,12 @@
case CHECK_URI_PERMISSION_TRANSACTION: {
data.enforceInterface(IContentProvider.descriptor);
String callingPkg = data.readString();
+ String featureId = data.readString();
Uri uri = Uri.CREATOR.createFromParcel(data);
int uid = data.readInt();
int modeFlags = data.readInt();
- int out = checkUriPermission(callingPkg, uri, uid, modeFlags);
+ int out = checkUriPermission(callingPkg, featureId, uri, uid, modeFlags);
reply.writeNoException();
reply.writeInt(out);
return true;
@@ -407,8 +424,9 @@
}
@Override
- public Cursor query(String callingPkg, Uri url, @Nullable String[] projection,
- @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)
+ public Cursor query(String callingPkg, @Nullable String featureId, Uri url,
+ @Nullable String[] projection, @Nullable Bundle queryArgs,
+ @Nullable ICancellationSignal cancellationSignal)
throws RemoteException {
BulkCursorToCursorAdaptor adaptor = new BulkCursorToCursorAdaptor();
Parcel data = Parcel.obtain();
@@ -417,6 +435,7 @@
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
+ data.writeString(featureId);
url.writeToParcel(data, 0);
int length = 0;
if (projection != null) {
@@ -478,7 +497,8 @@
}
@Override
- public Uri insert(String callingPkg, Uri url, ContentValues values) throws RemoteException
+ public Uri insert(String callingPkg, @Nullable String featureId, Uri url,
+ ContentValues values) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -486,6 +506,7 @@
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
+ data.writeString(featureId);
url.writeToParcel(data, 0);
values.writeToParcel(data, 0);
@@ -501,13 +522,15 @@
}
@Override
- public int bulkInsert(String callingPkg, Uri url, ContentValues[] values) throws RemoteException {
+ public int bulkInsert(String callingPkg, @Nullable String featureId, Uri url,
+ ContentValues[] values) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
+ data.writeString(featureId);
url.writeToParcel(data, 0);
data.writeTypedArray(values, 0);
@@ -523,14 +546,15 @@
}
@Override
- public ContentProviderResult[] applyBatch(String callingPkg, String authority,
- ArrayList<ContentProviderOperation> operations)
- throws RemoteException, OperationApplicationException {
+ public ContentProviderResult[] applyBatch(String callingPkg, @Nullable String featureId,
+ String authority, ArrayList<ContentProviderOperation> operations)
+ throws RemoteException, OperationApplicationException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
+ data.writeString(featureId);
data.writeString(authority);
data.writeInt(operations.size());
for (ContentProviderOperation operation : operations) {
@@ -549,14 +573,15 @@
}
@Override
- public int delete(String callingPkg, Uri url, String selection, String[] selectionArgs)
- throws RemoteException {
+ public int delete(String callingPkg, @Nullable String featureId, Uri url, String selection,
+ String[] selectionArgs) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
+ data.writeString(featureId);
url.writeToParcel(data, 0);
data.writeString(selection);
data.writeStringArray(selectionArgs);
@@ -573,14 +598,15 @@
}
@Override
- public int update(String callingPkg, Uri url, ContentValues values, String selection,
- String[] selectionArgs) throws RemoteException {
+ public int update(String callingPkg, @Nullable String featureId, Uri url,
+ ContentValues values, String selection, String[] selectionArgs) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
+ data.writeString(featureId);
url.writeToParcel(data, 0);
values.writeToParcel(data, 0);
data.writeString(selection);
@@ -598,8 +624,8 @@
}
@Override
- public ParcelFileDescriptor openFile(
- String callingPkg, Uri url, String mode, ICancellationSignal signal, IBinder token)
+ public ParcelFileDescriptor openFile(String callingPkg, @Nullable String featureId, Uri url,
+ String mode, ICancellationSignal signal, IBinder token)
throws RemoteException, FileNotFoundException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -607,6 +633,7 @@
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
+ data.writeString(featureId);
url.writeToParcel(data, 0);
data.writeString(mode);
data.writeStrongBinder(signal != null ? signal.asBinder() : null);
@@ -626,8 +653,8 @@
}
@Override
- public AssetFileDescriptor openAssetFile(
- String callingPkg, Uri url, String mode, ICancellationSignal signal)
+ public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String featureId,
+ Uri url, String mode, ICancellationSignal signal)
throws RemoteException, FileNotFoundException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -635,6 +662,7 @@
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
+ data.writeString(featureId);
url.writeToParcel(data, 0);
data.writeString(mode);
data.writeStrongBinder(signal != null ? signal.asBinder() : null);
@@ -653,14 +681,15 @@
}
@Override
- public Bundle call(String callingPkg, String authority, String method, String request,
- Bundle args) throws RemoteException {
+ public Bundle call(String callingPkg, @Nullable String featureId, String authority,
+ String method, String request, Bundle args) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
+ data.writeString(featureId);
data.writeString(authority);
data.writeString(method);
data.writeString(request);
@@ -700,14 +729,16 @@
}
@Override
- public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri url, String mimeType,
- Bundle opts, ICancellationSignal signal) throws RemoteException, FileNotFoundException {
+ public AssetFileDescriptor openTypedAssetFile(String callingPkg, @Nullable String featureId,
+ Uri url, String mimeType, Bundle opts, ICancellationSignal signal)
+ throws RemoteException, FileNotFoundException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
+ data.writeString(featureId);
url.writeToParcel(data, 0);
data.writeString(mimeType);
data.writeBundle(opts);
@@ -747,14 +778,15 @@
}
@Override
- public Uri canonicalize(String callingPkg, Uri url) throws RemoteException
- {
+ public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri url)
+ throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
+ data.writeString(featureId);
url.writeToParcel(data, 0);
mRemote.transact(IContentProvider.CANONICALIZE_TRANSACTION, data, reply, 0);
@@ -769,13 +801,15 @@
}
@Override
- public Uri uncanonicalize(String callingPkg, Uri url) throws RemoteException {
+ public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri url)
+ throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
+ data.writeString(featureId);
url.writeToParcel(data, 0);
mRemote.transact(IContentProvider.UNCANONICALIZE_TRANSACTION, data, reply, 0);
@@ -790,14 +824,15 @@
}
@Override
- public boolean refresh(String callingPkg, Uri url, Bundle args, ICancellationSignal signal)
- throws RemoteException {
+ public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle args,
+ ICancellationSignal signal) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
+ data.writeString(featureId);
url.writeToParcel(data, 0);
data.writeBundle(args);
data.writeStrongBinder(signal != null ? signal.asBinder() : null);
@@ -814,14 +849,15 @@
}
@Override
- public int checkUriPermission(String callingPkg, Uri url, int uid, int modeFlags)
- throws RemoteException {
+ public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri url, int uid,
+ int modeFlags) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
data.writeString(callingPkg);
+ data.writeString(featureId);
url.writeToParcel(data, 0);
data.writeInt(uid);
data.writeInt(modeFlags);
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 7f9ea76..2657cc5 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -649,6 +649,7 @@
public ContentResolver(@Nullable Context context, @Nullable ContentInterface wrapped) {
mContext = context != null ? context : ActivityThread.currentApplication();
mPackageName = mContext.getOpPackageName();
+ mFeatureId = mContext.getFeatureId();
mTargetSdkVersion = mContext.getApplicationInfo().targetSdkVersion;
mWrapped = wrapped;
}
@@ -968,7 +969,7 @@
cancellationSignal.setRemote(remoteCancellationSignal);
}
try {
- qCursor = unstableProvider.query(mPackageName, uri, projection,
+ qCursor = unstableProvider.query(mPackageName, mFeatureId, uri, projection,
queryArgs, remoteCancellationSignal);
} catch (DeadObjectException e) {
// The remote process has died... but we only hold an unstable
@@ -979,8 +980,8 @@
if (stableProvider == null) {
return null;
}
- qCursor = stableProvider.query(
- mPackageName, uri, projection, queryArgs, remoteCancellationSignal);
+ qCursor = stableProvider.query(mPackageName, mFeatureId, uri, projection,
+ queryArgs, remoteCancellationSignal);
}
if (qCursor == null) {
return null;
@@ -1070,7 +1071,7 @@
}
try {
- return provider.canonicalize(mPackageName, url);
+ return provider.canonicalize(mPackageName, mFeatureId, url);
} catch (RemoteException e) {
// Arbitrary and not worth documenting, as Activity
// Manager will kill this process shortly anyway.
@@ -1114,7 +1115,7 @@
}
try {
- return provider.uncanonicalize(mPackageName, url);
+ return provider.uncanonicalize(mPackageName, mFeatureId, url);
} catch (RemoteException e) {
// Arbitrary and not worth documenting, as Activity
// Manager will kill this process shortly anyway.
@@ -1163,7 +1164,8 @@
remoteCancellationSignal = provider.createCancellationSignal();
cancellationSignal.setRemote(remoteCancellationSignal);
}
- return provider.refresh(mPackageName, url, args, remoteCancellationSignal);
+ return provider.refresh(mPackageName, mFeatureId, url, args,
+ remoteCancellationSignal);
} catch (RemoteException e) {
// Arbitrary and not worth documenting, as Activity
// Manager will kill this process shortly anyway.
@@ -1564,7 +1566,7 @@
try {
fd = unstableProvider.openAssetFile(
- mPackageName, uri, mode, remoteCancellationSignal);
+ mPackageName, mFeatureId, uri, mode, remoteCancellationSignal);
if (fd == null) {
// The provider will be released by the finally{} clause
return null;
@@ -1579,7 +1581,7 @@
throw new FileNotFoundException("No content provider: " + uri);
}
fd = stableProvider.openAssetFile(
- mPackageName, uri, mode, remoteCancellationSignal);
+ mPackageName, mFeatureId, uri, mode, remoteCancellationSignal);
if (fd == null) {
// The provider will be released by the finally{} clause
return null;
@@ -1730,7 +1732,7 @@
try {
fd = unstableProvider.openTypedAssetFile(
- mPackageName, uri, mimeType, opts, remoteCancellationSignal);
+ mPackageName, mFeatureId, uri, mimeType, opts, remoteCancellationSignal);
if (fd == null) {
// The provider will be released by the finally{} clause
return null;
@@ -1745,7 +1747,7 @@
throw new FileNotFoundException("No content provider: " + uri);
}
fd = stableProvider.openTypedAssetFile(
- mPackageName, uri, mimeType, opts, remoteCancellationSignal);
+ mPackageName, mFeatureId, uri, mimeType, opts, remoteCancellationSignal);
if (fd == null) {
// The provider will be released by the finally{} clause
return null;
@@ -1870,7 +1872,7 @@
}
try {
long startTime = SystemClock.uptimeMillis();
- Uri createdRow = provider.insert(mPackageName, url, values);
+ Uri createdRow = provider.insert(mPackageName, mFeatureId, url, values);
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogUpdateToEventLog(durationMillis, url, "insert", null /* where */);
return createdRow;
@@ -1951,7 +1953,7 @@
}
try {
long startTime = SystemClock.uptimeMillis();
- int rowsCreated = provider.bulkInsert(mPackageName, url, values);
+ int rowsCreated = provider.bulkInsert(mPackageName, mFeatureId, url, values);
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogUpdateToEventLog(durationMillis, url, "bulkinsert", null /* where */);
return rowsCreated;
@@ -1991,7 +1993,8 @@
}
try {
long startTime = SystemClock.uptimeMillis();
- int rowsDeleted = provider.delete(mPackageName, url, where, selectionArgs);
+ int rowsDeleted = provider.delete(mPackageName, mFeatureId, url, where,
+ selectionArgs);
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogUpdateToEventLog(durationMillis, url, "delete", where);
return rowsDeleted;
@@ -2035,7 +2038,8 @@
}
try {
long startTime = SystemClock.uptimeMillis();
- int rowsUpdated = provider.update(mPackageName, uri, values, where, selectionArgs);
+ int rowsUpdated = provider.update(mPackageName, mFeatureId, uri, values, where,
+ selectionArgs);
long durationMillis = SystemClock.uptimeMillis() - startTime;
maybeLogUpdateToEventLog(durationMillis, uri, "update", where);
return rowsUpdated;
@@ -2084,7 +2088,8 @@
throw new IllegalArgumentException("Unknown authority " + authority);
}
try {
- final Bundle res = provider.call(mPackageName, authority, method, arg, extras);
+ final Bundle res = provider.call(mPackageName, mFeatureId, authority, method, arg,
+ extras);
Bundle.setDefusable(res, true);
return res;
} catch (RemoteException e) {
@@ -3436,6 +3441,11 @@
return mPackageName;
}
+ /** @hide */
+ public @Nullable String getFeatureId() {
+ return mFeatureId;
+ }
+
@UnsupportedAppUsage
private static volatile IContentService sContentService;
@UnsupportedAppUsage
@@ -3443,6 +3453,7 @@
@UnsupportedAppUsage
final String mPackageName;
+ final @Nullable String mFeatureId;
final int mTargetSdkVersion;
final ContentInterface mWrapped;
@@ -3638,19 +3649,19 @@
orientation.value = (extras != null) ? extras.getInt(EXTRA_ORIENTATION, 0) : 0;
return afd;
}), (ImageDecoder decoder, ImageInfo info, Source source) -> {
- decoder.setAllocator(allocator);
+ decoder.setAllocator(allocator);
- // One last-ditch check to see if we've been canceled.
- if (signal != null) signal.throwIfCanceled();
+ // One last-ditch check to see if we've been canceled.
+ if (signal != null) signal.throwIfCanceled();
- // We requested a rough thumbnail size, but the remote size may have
- // returned something giant, so defensively scale down as needed.
- final int widthSample = info.getSize().getWidth() / size.getWidth();
- final int heightSample = info.getSize().getHeight() / size.getHeight();
- final int sample = Math.min(widthSample, heightSample);
- if (sample > 1) {
- decoder.setTargetSampleSize(sample);
- }
+ // We requested a rough thumbnail size, but the remote size may have
+ // returned something giant, so defensively scale down as needed.
+ final int widthSample = info.getSize().getWidth() / size.getWidth();
+ final int heightSample = info.getSize().getHeight() / size.getHeight();
+ final int sample = Math.max(widthSample, heightSample);
+ if (sample > 1) {
+ decoder.setTargetSampleSize(sample);
+ }
});
// Transform the bitmap if requested. We use a side-channel to
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index fd061d0..862ec50 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2417,6 +2417,44 @@
@Nullable String initialData, @Nullable Bundle initialExtras);
/**
+ * Version of
+ * {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String,
+ * Bundle)} that allows you to specify the App Op to enforce restrictions on which receivers
+ * the broadcast will be sent to.
+ *
+ * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
+ *
+ * @param intent The Intent to broadcast; all receivers matching this
+ * Intent will receive the broadcast.
+ * @param receiverPermission String naming a permissions that
+ * a receiver must hold in order to receive your broadcast.
+ * If null, no permission is required.
+ * @param receiverAppOp The app op associated with the broadcast. If null, no appOp is
+ * required. If both receiverAppOp and receiverPermission are non-null,
+ * a receiver must have both of them to
+ * receive the broadcast
+ * @param resultReceiver Your own BroadcastReceiver to treat as the final
+ * receiver of the broadcast.
+ * @param scheduler A custom Handler with which to schedule the
+ * resultReceiver callback; if null it will be
+ * scheduled in the Context's main thread.
+ * @param initialCode An initial value for the result code. Often
+ * Activity.RESULT_OK.
+ * @param initialData An initial value for the result data. Often
+ * null.
+ * @param initialExtras An initial value for the result extras. Often
+ * null.
+ *
+ * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
+ */
+ public void sendOrderedBroadcast(@RequiresPermission @NonNull Intent intent,
+ @Nullable String receiverPermission, @Nullable String receiverAppOp,
+ @Nullable BroadcastReceiver resultReceiver, @Nullable Handler scheduler,
+ int initialCode, @Nullable String initialData, @Nullable Bundle initialExtras) {
+ throw new RuntimeException("Not implemented. Must override in a subclass.");
+ }
+
+ /**
* <p>Perform a {@link #sendBroadcast(Intent)} that is "sticky," meaning the
* Intent you are sending stays around after the broadcast is complete,
* so that others can quickly retrieve that data through the return
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index d5d0dce..6174018 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -16,7 +16,9 @@
package android.content;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
@@ -62,12 +64,12 @@
public ContextWrapper(Context base) {
mBase = base;
}
-
+
/**
* Set the base context for this ContextWrapper. All calls will then be
* delegated to the base context. Throws
* IllegalStateException if a base context has already been set.
- *
+ *
* @param base The new base context for this wrapper.
*/
protected void attachBaseContext(Context base) {
@@ -118,7 +120,7 @@
public Context getApplicationContext() {
return mBase.getApplicationContext();
}
-
+
@Override
public void setTheme(int resid) {
mBase.setTheme(resid);
@@ -169,7 +171,7 @@
public ApplicationInfo getApplicationInfo() {
return mBase.getApplicationInfo();
}
-
+
@Override
public String getPackageResourcePath() {
return mBase.getPackageResourcePath();
@@ -209,13 +211,13 @@
@Override
public FileInputStream openFileInput(String name)
- throws FileNotFoundException {
+ throws FileNotFoundException {
return mBase.openFileInput(name);
}
@Override
public FileOutputStream openFileOutput(String name, int mode)
- throws FileNotFoundException {
+ throws FileNotFoundException {
return mBase.openFileOutput(name, mode);
}
@@ -449,7 +451,7 @@
mBase.startIntentSender(intent, fillInIntent, flagsMask,
flagsValues, extraFlags, options);
}
-
+
@Override
public void sendBroadcast(Intent intent) {
mBase.sendBroadcast(intent);
@@ -494,9 +496,9 @@
@Override
public void sendOrderedBroadcast(
- Intent intent, String receiverPermission, BroadcastReceiver resultReceiver,
- Handler scheduler, int initialCode, String initialData,
- Bundle initialExtras) {
+ Intent intent, String receiverPermission, BroadcastReceiver resultReceiver,
+ Handler scheduler, int initialCode, String initialData,
+ Bundle initialExtras) {
mBase.sendOrderedBroadcast(intent, receiverPermission,
resultReceiver, scheduler, initialCode,
initialData, initialExtras);
@@ -506,7 +508,8 @@
@SystemApi
@Override
public void sendOrderedBroadcast(
- Intent intent, String receiverPermission, Bundle options, BroadcastReceiver resultReceiver,
+ Intent intent, String receiverPermission, Bundle options,
+ BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData,
Bundle initialExtras) {
mBase.sendOrderedBroadcast(intent, receiverPermission,
@@ -517,9 +520,9 @@
/** @hide */
@Override
public void sendOrderedBroadcast(
- Intent intent, String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
- Handler scheduler, int initialCode, String initialData,
- Bundle initialExtras) {
+ Intent intent, String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
+ Handler scheduler, int initialCode, String initialData,
+ Bundle initialExtras) {
mBase.sendOrderedBroadcast(intent, receiverPermission, appOp,
resultReceiver, scheduler, initialCode,
initialData, initialExtras);
@@ -577,6 +580,15 @@
}
@Override
+ public void sendOrderedBroadcast(@RequiresPermission @NonNull Intent intent,
+ @Nullable String receiverPermission, @Nullable String receiverAppOp,
+ @Nullable BroadcastReceiver resultReceiver, @Nullable Handler scheduler,
+ int initialCode, @Nullable String initialData, @Nullable Bundle initialExtras) {
+ mBase.sendOrderedBroadcast(intent, receiverPermission, receiverAppOp, resultReceiver,
+ scheduler, initialCode, initialData, initialExtras);
+ }
+
+ @Override
@Deprecated
public void sendStickyBroadcast(Intent intent) {
mBase.sendStickyBroadcast(intent);
@@ -928,6 +940,11 @@
}
@Override
+ public @NonNull Context createFeatureContext(@Nullable String featureId) {
+ return mBase.createFeatureContext(featureId);
+ }
+
+ @Override
public boolean isRestricted() {
return mBase.isRestricted();
}
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index fade0ab..d2c97c4 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -16,7 +16,6 @@
package android.content;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
@@ -38,66 +37,96 @@
* @hide
*/
public interface IContentProvider extends IInterface {
- public Cursor query(String callingPkg, Uri url, @Nullable String[] projection,
+ public Cursor query(String callingPkg, @Nullable String featureId, Uri url,
+ @Nullable String[] projection,
@Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)
throws RemoteException;
public String getType(Uri url) throws RemoteException;
- @UnsupportedAppUsage
- public Uri insert(String callingPkg, Uri url, ContentValues initialValues)
- throws RemoteException;
- @UnsupportedAppUsage
- public int bulkInsert(String callingPkg, Uri url, ContentValues[] initialValues)
- throws RemoteException;
- @UnsupportedAppUsage
- public int delete(String callingPkg, Uri url, String selection, String[] selectionArgs)
- throws RemoteException;
- @UnsupportedAppUsage
- public int update(String callingPkg, Uri url, ContentValues values, String selection,
- String[] selectionArgs) throws RemoteException;
- public ParcelFileDescriptor openFile(
- String callingPkg, Uri url, String mode, ICancellationSignal signal,
- IBinder callerToken)
- throws RemoteException, FileNotFoundException;
- public AssetFileDescriptor openAssetFile(
- String callingPkg, Uri url, String mode, ICancellationSignal signal)
- throws RemoteException, FileNotFoundException;
-
@Deprecated
- public default ContentProviderResult[] applyBatch(String callingPkg,
- ArrayList<ContentProviderOperation> operations)
- throws RemoteException, OperationApplicationException {
- return applyBatch(callingPkg, "unknown", operations);
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
+ + "ContentProviderClient#insert(android.net.Uri, android.content.ContentValues)} "
+ + "instead")
+ public default Uri insert(String callingPkg, Uri url, ContentValues initialValues)
+ throws RemoteException {
+ return insert(callingPkg, null, url, initialValues);
}
+ public Uri insert(String callingPkg, String featureId, Uri url, ContentValues initialValues)
+ throws RemoteException;
+ @Deprecated
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
+ + "ContentProviderClient#bulkInsert(android.net.Uri, android.content.ContentValues[])"
+ + "} instead")
+ public default int bulkInsert(String callingPkg, Uri url, ContentValues[] initialValues)
+ throws RemoteException {
+ return bulkInsert(callingPkg, null, url, initialValues);
+ }
+ public int bulkInsert(String callingPkg, String featureId, Uri url,
+ ContentValues[] initialValues) throws RemoteException;
+ @Deprecated
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
+ + "ContentProviderClient#delete(android.net.Uri, java.lang.String, java.lang"
+ + ".String[])} instead")
+ public default int delete(String callingPkg, Uri url, String selection, String[] selectionArgs)
+ throws RemoteException {
+ return delete(callingPkg, null, url, selection, selectionArgs);
+ }
+ public int delete(String callingPkg, String featureId, Uri url, String selection,
+ String[] selectionArgs) throws RemoteException;
+ @Deprecated
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
+ + "ContentProviderClient#update(android.net.Uri, android.content.ContentValues, java"
+ + ".lang.String, java.lang.String[])} instead")
+ public default int update(String callingPkg, Uri url, ContentValues values, String selection,
+ String[] selectionArgs) throws RemoteException {
+ return update(callingPkg, null, url, values, selection, selectionArgs);
+ }
+ public int update(String callingPkg, String featureId, Uri url, ContentValues values,
+ String selection, String[] selectionArgs) throws RemoteException;
- public ContentProviderResult[] applyBatch(String callingPkg, String authority,
- ArrayList<ContentProviderOperation> operations)
+ public ParcelFileDescriptor openFile(String callingPkg, @Nullable String featureId, Uri url,
+ String mode, ICancellationSignal signal, IBinder callerToken)
+ throws RemoteException, FileNotFoundException;
+
+ public AssetFileDescriptor openAssetFile(String callingPkg, @Nullable String featureId,
+ Uri url, String mode, ICancellationSignal signal)
+ throws RemoteException, FileNotFoundException;
+
+ public ContentProviderResult[] applyBatch(String callingPkg, @Nullable String featureId,
+ String authority, ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException;
@Deprecated
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
+ + "ContentProviderClient#call(java.lang.String, java.lang.String, android.os.Bundle)} "
+ + "instead")
public default Bundle call(String callingPkg, String method,
@Nullable String arg, @Nullable Bundle extras) throws RemoteException {
- return call(callingPkg, "unknown", method, arg, extras);
+ return call(callingPkg, null, "unknown", method, arg, extras);
}
- public Bundle call(String callingPkg, String authority, String method,
- @Nullable String arg, @Nullable Bundle extras) throws RemoteException;
+ public Bundle call(String callingPkg, @Nullable String featureId, String authority,
+ String method, @Nullable String arg, @Nullable Bundle extras) throws RemoteException;
- public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags)
- throws RemoteException;
+ public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri, int uid,
+ int modeFlags) throws RemoteException;
public ICancellationSignal createCancellationSignal() throws RemoteException;
- public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException;
- public Uri uncanonicalize(String callingPkg, Uri uri) throws RemoteException;
+ public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri)
+ throws RemoteException;
- public boolean refresh(String callingPkg, Uri url, @Nullable Bundle args,
- ICancellationSignal cancellationSignal) throws RemoteException;
+ public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri)
+ throws RemoteException;
+
+ public boolean refresh(String callingPkg, @Nullable String featureId, Uri url,
+ @Nullable Bundle args, ICancellationSignal cancellationSignal) throws RemoteException;
// Data interchange.
public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException;
- public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri url, String mimeType,
- Bundle opts, ICancellationSignal signal) throws RemoteException, FileNotFoundException;
+
+ public AssetFileDescriptor openTypedAssetFile(String callingPkg, @Nullable String featureId,
+ Uri url, String mimeType, Bundle opts, ICancellationSignal signal)
+ throws RemoteException, FileNotFoundException;
/* IPC constants */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
diff --git a/core/java/android/content/PermissionChecker.java b/core/java/android/content/PermissionChecker.java
index 85f96fc..6954b31 100644
--- a/core/java/android/content/PermissionChecker.java
+++ b/core/java/android/content/PermissionChecker.java
@@ -114,6 +114,7 @@
* @param uid The uid for which to check.
* @param packageName The package name for which to check. If null the
* the first package for the calling UID will be used.
+ * @param featureId Feature in the package
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
* or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
* @param message A message describing the reason the permission was checked
@@ -123,8 +124,8 @@
@PermissionResult
public static int checkPermissionForDataDelivery(@NonNull Context context,
@NonNull String permission, int pid, int uid, @Nullable String packageName,
- @Nullable String message) {
- return checkPermissionCommon(context, permission, pid, uid, packageName, message,
+ @Nullable String featureId, @Nullable String message) {
+ return checkPermissionCommon(context, permission, pid, uid, packageName, featureId, message,
true /*forDataDelivery*/);
}
@@ -161,8 +162,8 @@
@PermissionResult
public static int checkPermissionForPreflight(@NonNull Context context,
@NonNull String permission, int pid, int uid, @Nullable String packageName) {
- return checkPermissionCommon(context, permission, pid, uid, packageName, null /*message*/,
- false /*forDataDelivery*/);
+ return checkPermissionCommon(context, permission, pid, uid, packageName, null /*featureId*/,
+ null /*message*/, false /*forDataDelivery*/);
}
/**
@@ -197,7 +198,7 @@
public static int checkSelfPermissionForDataDelivery(@NonNull Context context,
@NonNull String permission, @Nullable String message) {
return checkPermissionForDataDelivery(context, permission, Process.myPid(),
- Process.myUid(), context.getPackageName(), message);
+ Process.myUid(), context.getPackageName(), context.getFeatureId(), message);
}
/**
@@ -256,6 +257,7 @@
* @param permission The permission to check.
* @param packageName The package name making the IPC. If null the
* the first package for the calling UID will be used.
+ * @param featureId The feature inside of the app
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
* or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
* @param message A message describing the reason the permission was checked
@@ -264,12 +266,13 @@
*/
@PermissionResult
public static int checkCallingPermissionForDataDelivery(@NonNull Context context,
- @NonNull String permission, @Nullable String packageName, @Nullable String message) {
+ @NonNull String permission, @Nullable String packageName,
+ @Nullable String featureId, @Nullable String message) {
if (Binder.getCallingPid() == Process.myPid()) {
return PERMISSION_DENIED;
}
return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
- Binder.getCallingUid(), packageName, message);
+ Binder.getCallingUid(), packageName, featureId, message);
}
/**
@@ -331,17 +334,20 @@
* @param permission The permission to check.
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
* or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
+ * @param featureId feature Id of caller (if not self)
* @param message A message describing the reason the permission was checked
*
* @see #checkCallingOrSelfPermissionForPreflight(Context, String)
*/
@PermissionResult
public static int checkCallingOrSelfPermissionForDataDelivery(@NonNull Context context,
- @NonNull String permission, @Nullable String message) {
+ @NonNull String permission, @Nullable String featureId, @Nullable String message) {
String packageName = (Binder.getCallingPid() == Process.myPid())
? context.getPackageName() : null;
+ featureId = (Binder.getCallingPid() == Process.myPid())
+ ? context.getFeatureId() : featureId;
return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
- Binder.getCallingUid(), packageName, message);
+ Binder.getCallingUid(), packageName, featureId, message);
}
/**
@@ -360,15 +366,15 @@
* app's fg/gb state) and this check will not leave a trace that permission protected
* data was delivered. When you are about to deliver the location data to a registered
* listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context,
- * String, String)} which will evaluate the permission access based on the current fg/bg state
- * of the app and leave a record that the data was accessed.
+ * String, String, String)} which will evaluate the permission access based on the current
+ * fg/bg state of the app and leave a record that the data was accessed.
*
* @param context Context for accessing resources.
* @param permission The permission to check.
* @return The permission check result which is either {@link #PERMISSION_GRANTED}
* or {@link #PERMISSION_DENIED} or {@link #PERMISSION_DENIED_APP_OP}.
*
- * @see #checkCallingOrSelfPermissionForDataDelivery(Context, String, String)
+ * @see #checkCallingOrSelfPermissionForDataDelivery(Context, String, String, String)
*/
@PermissionResult
public static int checkCallingOrSelfPermissionForPreflight(@NonNull Context context,
@@ -380,8 +386,8 @@
}
private static int checkPermissionCommon(@NonNull Context context, @NonNull String permission,
- int pid, int uid, @Nullable String packageName, @Nullable String message,
- boolean forDataDelivery) {
+ int pid, int uid, @Nullable String packageName, @Nullable String featureId,
+ @Nullable String message, boolean forDataDelivery) {
if (context.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_DENIED) {
return PERMISSION_DENIED;
}
@@ -401,8 +407,7 @@
}
if (forDataDelivery) {
- // TODO moltmann: Set correct feature id
- if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid, null, message)
+ if (appOpsManager.noteProxyOpNoThrow(op, packageName, uid, featureId, message)
!= AppOpsManager.MODE_ALLOWED) {
return PERMISSION_DENIED_APP_OP;
}
diff --git a/core/java/android/content/SyncStats.java b/core/java/android/content/SyncStats.java
index 03b2250e..9596a60 100644
--- a/core/java/android/content/SyncStats.java
+++ b/core/java/android/content/SyncStats.java
@@ -58,7 +58,7 @@
* attempted to update or delete a version of a resource on the server. This is expected
* to clear itself automatically once the new state is retrieved from the server,
* though it may remain until the user intervenes manually, perhaps by clearing the
- * local storage and starting over frmo scratch. This is considered a hard error.
+ * local storage and starting over from scratch. This is considered a hard error.
*/
public long numConflictDetectedExceptions;
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 578d086..053444b 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1587,6 +1587,80 @@
}
/**
+ * Copies the fields specified by mask from delta into this Configuration object. This will
+ * copy anything allowed by the mask (including undefined values).
+ * @hide
+ */
+ public void setTo(@NonNull Configuration delta, @Config int mask,
+ @WindowConfiguration.WindowConfig int windowMask) {
+ if ((mask & ActivityInfo.CONFIG_FONT_SCALE) != 0) {
+ fontScale = delta.fontScale;
+ }
+ if ((mask & ActivityInfo.CONFIG_MCC) != 0) {
+ mcc = delta.mcc;
+ }
+ if ((mask & ActivityInfo.CONFIG_MNC) != 0) {
+ mnc = delta.mnc;
+ }
+ if ((mask & ActivityInfo.CONFIG_LOCALE) != 0) {
+ mLocaleList = delta.mLocaleList;
+ if (!mLocaleList.isEmpty()) {
+ locale = (Locale) delta.locale.clone();
+ }
+ }
+ if ((mask & ActivityInfo.CONFIG_LAYOUT_DIRECTION) != 0) {
+ final int deltaScreenLayoutDir = delta.screenLayout & SCREENLAYOUT_LAYOUTDIR_MASK;
+ screenLayout = (screenLayout & ~SCREENLAYOUT_LAYOUTDIR_MASK) | deltaScreenLayoutDir;
+ }
+ if ((mask & ActivityInfo.CONFIG_LOCALE) != 0) {
+ userSetLocale = delta.userSetLocale;
+ }
+ if ((mask & ActivityInfo.CONFIG_TOUCHSCREEN) != 0) {
+ touchscreen = delta.touchscreen;
+ }
+ if ((mask & ActivityInfo.CONFIG_KEYBOARD) != 0) {
+ keyboard = delta.keyboard;
+ }
+ if ((mask & ActivityInfo.CONFIG_KEYBOARD_HIDDEN) != 0) {
+ keyboardHidden = delta.keyboardHidden;
+ hardKeyboardHidden = delta.hardKeyboardHidden;
+ navigationHidden = delta.navigationHidden;
+ }
+ if ((mask & ActivityInfo.CONFIG_NAVIGATION) != 0) {
+ navigation = delta.navigation;
+ }
+ if ((mask & ActivityInfo.CONFIG_ORIENTATION) != 0) {
+ orientation = delta.orientation;
+ }
+ if ((mask & ActivityInfo.CONFIG_SCREEN_LAYOUT) != 0) {
+ // Not enough granularity for each component unfortunately.
+ screenLayout = screenLayout | (delta.screenLayout & ~SCREENLAYOUT_LAYOUTDIR_MASK);
+ }
+ if ((mask & ActivityInfo.CONFIG_COLOR_MODE) != 0) {
+ colorMode = delta.colorMode;
+ }
+ if ((mask & ActivityInfo.CONFIG_UI_MODE) != 0) {
+ uiMode = delta.uiMode;
+ }
+ if ((mask & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) {
+ screenWidthDp = delta.screenWidthDp;
+ screenHeightDp = delta.screenHeightDp;
+ }
+ if ((mask & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
+ smallestScreenWidthDp = delta.smallestScreenWidthDp;
+ }
+ if ((mask & ActivityInfo.CONFIG_DENSITY) != 0) {
+ densityDpi = delta.densityDpi;
+ }
+ if ((mask & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) {
+ assetsSeq = delta.assetsSeq;
+ }
+ if ((mask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0) {
+ windowConfiguration.setTo(delta.windowConfiguration, windowMask);
+ }
+ }
+
+ /**
* Return a bit mask of the differences between this Configuration
* object and the given one. Does not change the values of either. Any
* undefined fields in <var>delta</var> are ignored.
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index fbcc785..1f29d1a 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1125,6 +1125,37 @@
new Key<android.util.Range<Integer>>("android.control.postRawSensitivityBoostRange", new TypeReference<android.util.Range<Integer>>() {{ }});
/**
+ * <p>The list of bokeh modes that are supported by this camera device, and each bokeh mode's
+ * maximum streaming (non-stall) size with bokeh effect.</p>
+ * <p>For OFF mode, the camera behaves normally with no bokeh effect.</p>
+ * <p>For STILL_CAPTURE mode, the maximum streaming dimension specifies the limit under which
+ * bokeh is effective when capture intent is PREVIEW. Note that when capture intent is
+ * PREVIEW, the bokeh effect may not be as high quality compared to STILL_CAPTURE intent
+ * in order to maintain reasonable frame rate. The maximum streaming dimension must be one
+ * of the YUV_420_888 or PRIVATE resolutions in availableStreamConfigurations, or (0, 0)
+ * if preview bokeh is not supported. If the application configures a stream larger than
+ * the maximum streaming dimension, bokeh effect may not be applied for this stream for
+ * PREVIEW intent.</p>
+ * <p>For CONTINUOUS mode, the maximum streaming dimension specifies the limit under which
+ * bokeh is effective. This dimension must be one of the YUV_420_888 or PRIVATE resolutions
+ * in availableStreamConfigurations, and if the sensor maximum resolution is larger than or
+ * equal to 1080p, the maximum streaming dimension must be at least 1080p. If the
+ * application configures a stream with larger dimension, the stream may not have bokeh
+ * effect applied.</p>
+ * <p><b>Units</b>: (mode, width, height)</p>
+ * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+ * <p><b>Limited capability</b> -
+ * Present on all camera devices that report being at least {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED HARDWARE_LEVEL_LIMITED} devices in the
+ * {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} key</p>
+ *
+ * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
+ */
+ @PublicKey
+ @NonNull
+ public static final Key<android.hardware.camera2.params.CapabilityAndMaxSize[]> CONTROL_AVAILABLE_BOKEH_CAPABILITIES =
+ new Key<android.hardware.camera2.params.CapabilityAndMaxSize[]>("android.control.availableBokehCapabilities", android.hardware.camera2.params.CapabilityAndMaxSize[].class);
+
+ /**
* <p>List of edge enhancement modes for {@link CaptureRequest#EDGE_MODE android.edge.mode} that are supported by this camera
* device.</p>
* <p>Full-capability camera devices must always support OFF; camera devices that support
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 2fa6125..799c716 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -2444,6 +2444,34 @@
public static final int CONTROL_VIDEO_STABILIZATION_MODE_ON = 1;
//
+ // Enumeration values for CaptureRequest#CONTROL_BOKEH_MODE
+ //
+
+ /**
+ * <p>Bokeh mode is disabled.</p>
+ * @see CaptureRequest#CONTROL_BOKEH_MODE
+ */
+ public static final int CONTROL_BOKEH_MODE_OFF = 0;
+
+ /**
+ * <p>High quality bokeh mode is enabled for all non-raw streams (including YUV,
+ * JPEG, and IMPLEMENTATION_DEFINED) when capture intent is STILL_CAPTURE. Due to the
+ * extra image processing, this mode may introduce additional stall to non-raw streams.
+ * This mode should be used in high quality still capture use case.</p>
+ * @see CaptureRequest#CONTROL_BOKEH_MODE
+ */
+ public static final int CONTROL_BOKEH_MODE_STILL_CAPTURE = 1;
+
+ /**
+ * <p>Bokeh effect must not slow down capture rate relative to sensor raw output,
+ * and the effect is applied to all processed streams no larger than the maximum
+ * streaming dimension. This mode should be used if performance and power are a
+ * priority, such as video recording.</p>
+ * @see CaptureRequest#CONTROL_BOKEH_MODE
+ */
+ public static final int CONTROL_BOKEH_MODE_CONTINUOUS = 2;
+
+ //
// Enumeration values for CaptureRequest#EDGE_MODE
//
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 43c197a..5c76dff 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -994,7 +994,7 @@
* application controls how the color mapping is performed.</p>
* <p>We define the expected processing pipeline below. For consistency
* across devices, this is always the case with TRANSFORM_MATRIX.</p>
- * <p>When either FULL or HIGH_QUALITY is used, the camera device may
+ * <p>When either FAST or HIGH_QUALITY is used, the camera device may
* do additional processing but {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} and
* {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform} will still be provided by the
* camera device (in the results) and be roughly correct.</p>
@@ -2094,6 +2094,52 @@
new Key<Boolean>("android.control.enableZsl", boolean.class);
/**
+ * <p>Whether bokeh mode is enabled for a particular capture request.</p>
+ * <p>With bokeh mode, the camera device may blur out the parts of scene that are not in
+ * focus, creating a bokeh (or shallow depth of field) effect for people or objects.</p>
+ * <p>When set to STILL_CAPTURE bokeh mode with STILL_CAPTURE capture intent, due to the extra
+ * processing needed for high quality bokeh effect, the stall may be longer than when
+ * capture intent is not STILL_CAPTURE.</p>
+ * <p>When set to STILL_CAPTURE bokeh mode with PREVIEW capture intent,</p>
+ * <ul>
+ * <li>If the camera device has BURST_CAPTURE capability, the frame rate requirement of
+ * BURST_CAPTURE must still be met.</li>
+ * <li>All streams not larger than the maximum streaming dimension for STILL_CAPTURE mode
+ * (queried via {@link android.hardware.camera2.CameraCharacteristics#CONTROL_AVAILABLE_BOKEH_CAPABILITIES })
+ * will have preview bokeh effect applied.</li>
+ * </ul>
+ * <p>When set to CONTINUOUS mode, configured streams dimension should not exceed this mode's
+ * maximum streaming dimension in order to have bokeh effect applied. Bokeh effect may not
+ * be available for streams larger than the maximum streaming dimension.</p>
+ * <p>Switching between different bokeh modes may involve reconfiguration of the camera
+ * pipeline, resulting in long latency. The application should check this key against the
+ * available session keys queried via
+ * {@link android.hardware.camera2.CameraCharacteristics#getAvailableSessionKeys }.</p>
+ * <p>When bokeh mode is on, the camera device may override certain control parameters, such as
+ * reduce frame rate or use face priority scene mode, to achieve best power and quality
+ * tradeoffs. When turned on, AE, AWB, and AF run in auto modes, and only the mandatory
+ * stream combinations of LIMITED hardware level are guaranteed.</p>
+ * <p>For a logical multi-camera, bokeh may be implemented by stereo vision from sub-cameras
+ * with different field of view. As a result, when bokeh mode is enabled, the camera device
+ * may override android.scaler.CropRegion, and the field of view will be smaller than when
+ * bokeh mode is off.</p>
+ * <p><b>Possible values:</b>
+ * <ul>
+ * <li>{@link #CONTROL_BOKEH_MODE_OFF OFF}</li>
+ * <li>{@link #CONTROL_BOKEH_MODE_STILL_CAPTURE STILL_CAPTURE}</li>
+ * <li>{@link #CONTROL_BOKEH_MODE_CONTINUOUS CONTINUOUS}</li>
+ * </ul></p>
+ * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+ * @see #CONTROL_BOKEH_MODE_OFF
+ * @see #CONTROL_BOKEH_MODE_STILL_CAPTURE
+ * @see #CONTROL_BOKEH_MODE_CONTINUOUS
+ */
+ @PublicKey
+ @NonNull
+ public static final Key<Integer> CONTROL_BOKEH_MODE =
+ new Key<Integer>("android.control.bokehMode", int.class);
+
+ /**
* <p>Operation mode for edge
* enhancement.</p>
* <p>Edge enhancement improves sharpness and details in the captured image. OFF means
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index 1007fd9..2d0ec6d 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -398,7 +398,7 @@
* application controls how the color mapping is performed.</p>
* <p>We define the expected processing pipeline below. For consistency
* across devices, this is always the case with TRANSFORM_MATRIX.</p>
- * <p>When either FULL or HIGH_QUALITY is used, the camera device may
+ * <p>When either FAST or HIGH_QUALITY is used, the camera device may
* do additional processing but {@link CaptureRequest#COLOR_CORRECTION_GAINS android.colorCorrection.gains} and
* {@link CaptureRequest#COLOR_CORRECTION_TRANSFORM android.colorCorrection.transform} will still be provided by the
* camera device (in the results) and be roughly correct.</p>
@@ -2324,6 +2324,52 @@
new Key<Integer>("android.control.afSceneChange", int.class);
/**
+ * <p>Whether bokeh mode is enabled for a particular capture request.</p>
+ * <p>With bokeh mode, the camera device may blur out the parts of scene that are not in
+ * focus, creating a bokeh (or shallow depth of field) effect for people or objects.</p>
+ * <p>When set to STILL_CAPTURE bokeh mode with STILL_CAPTURE capture intent, due to the extra
+ * processing needed for high quality bokeh effect, the stall may be longer than when
+ * capture intent is not STILL_CAPTURE.</p>
+ * <p>When set to STILL_CAPTURE bokeh mode with PREVIEW capture intent,</p>
+ * <ul>
+ * <li>If the camera device has BURST_CAPTURE capability, the frame rate requirement of
+ * BURST_CAPTURE must still be met.</li>
+ * <li>All streams not larger than the maximum streaming dimension for STILL_CAPTURE mode
+ * (queried via {@link android.hardware.camera2.CameraCharacteristics#CONTROL_AVAILABLE_BOKEH_CAPABILITIES })
+ * will have preview bokeh effect applied.</li>
+ * </ul>
+ * <p>When set to CONTINUOUS mode, configured streams dimension should not exceed this mode's
+ * maximum streaming dimension in order to have bokeh effect applied. Bokeh effect may not
+ * be available for streams larger than the maximum streaming dimension.</p>
+ * <p>Switching between different bokeh modes may involve reconfiguration of the camera
+ * pipeline, resulting in long latency. The application should check this key against the
+ * available session keys queried via
+ * {@link android.hardware.camera2.CameraCharacteristics#getAvailableSessionKeys }.</p>
+ * <p>When bokeh mode is on, the camera device may override certain control parameters, such as
+ * reduce frame rate or use face priority scene mode, to achieve best power and quality
+ * tradeoffs. When turned on, AE, AWB, and AF run in auto modes, and only the mandatory
+ * stream combinations of LIMITED hardware level are guaranteed.</p>
+ * <p>For a logical multi-camera, bokeh may be implemented by stereo vision from sub-cameras
+ * with different field of view. As a result, when bokeh mode is enabled, the camera device
+ * may override android.scaler.CropRegion, and the field of view will be smaller than when
+ * bokeh mode is off.</p>
+ * <p><b>Possible values:</b>
+ * <ul>
+ * <li>{@link #CONTROL_BOKEH_MODE_OFF OFF}</li>
+ * <li>{@link #CONTROL_BOKEH_MODE_STILL_CAPTURE STILL_CAPTURE}</li>
+ * <li>{@link #CONTROL_BOKEH_MODE_CONTINUOUS CONTINUOUS}</li>
+ * </ul></p>
+ * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
+ * @see #CONTROL_BOKEH_MODE_OFF
+ * @see #CONTROL_BOKEH_MODE_STILL_CAPTURE
+ * @see #CONTROL_BOKEH_MODE_CONTINUOUS
+ */
+ @PublicKey
+ @NonNull
+ public static final Key<Integer> CONTROL_BOKEH_MODE =
+ new Key<Integer>("android.control.bokehMode", int.class);
+
+ /**
* <p>Operation mode for edge
* enhancement.</p>
* <p>Edge enhancement improves sharpness and details in the captured image. OFF means
diff --git a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
index e909c00..7c1ddad 100644
--- a/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
+++ b/core/java/android/hardware/camera2/impl/CameraMetadataNative.java
@@ -21,6 +21,7 @@
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
@@ -29,6 +30,7 @@
import android.hardware.camera2.marshal.Marshaler;
import android.hardware.camera2.marshal.impl.MarshalQueryableArray;
import android.hardware.camera2.marshal.impl.MarshalQueryableBlackLevelPattern;
+import android.hardware.camera2.marshal.impl.MarshalQueryableCapabilityAndMaxSize;
import android.hardware.camera2.marshal.impl.MarshalQueryableBoolean;
import android.hardware.camera2.marshal.impl.MarshalQueryableColorSpaceTransform;
import android.hardware.camera2.marshal.impl.MarshalQueryableEnum;
@@ -48,6 +50,7 @@
import android.hardware.camera2.marshal.impl.MarshalQueryableStreamConfiguration;
import android.hardware.camera2.marshal.impl.MarshalQueryableStreamConfigurationDuration;
import android.hardware.camera2.marshal.impl.MarshalQueryableString;
+import android.hardware.camera2.params.CapabilityAndMaxSize;
import android.hardware.camera2.params.Face;
import android.hardware.camera2.params.HighSpeedVideoConfiguration;
import android.hardware.camera2.params.LensShadingMap;
@@ -671,6 +674,15 @@
return (T) metadata.getOisSamples();
}
});
+ sGetCommandMap.put(
+ CameraCharacteristics.CONTROL_AVAILABLE_BOKEH_CAPABILITIES.getNativeKey(),
+ new GetCommand() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T getValue(CameraMetadataNative metadata, Key<T> key) {
+ return (T) metadata.getBokehCapabilities();
+ }
+ });
}
private int[] getAvailableFormats() {
@@ -1373,6 +1385,24 @@
return samples;
}
+ private CapabilityAndMaxSize[] getBokehCapabilities() {
+ CapabilityAndMaxSize[] bcs = getBase(
+ CameraCharacteristics.CONTROL_AVAILABLE_BOKEH_CAPABILITIES);
+
+ if (bcs != null) {
+ for (CapabilityAndMaxSize bc : bcs) {
+ if (bc.getMode() < CameraMetadata.CONTROL_BOKEH_MODE_OFF ||
+ bc.getMode() > CameraMetadata.CONTROL_BOKEH_MODE_CONTINUOUS) {
+ throw new AssertionError(String.format(
+ "bokehMode %d is out of valid range [%d, %d]", bc.getMode(),
+ CameraMetadata.CONTROL_BOKEH_MODE_OFF,
+ CameraMetadata.CONTROL_BOKEH_MODE_CONTINUOUS));
+ }
+ }
+ }
+ return bcs;
+ }
+
private <T> void setBase(CameraCharacteristics.Key<T> key, T value) {
setBase(key.getNativeKey(), value);
}
@@ -1750,6 +1780,7 @@
new MarshalQueryableBlackLevelPattern(),
new MarshalQueryableHighSpeedVideoConfiguration(),
new MarshalQueryableRecommendedStreamConfiguration(),
+ new MarshalQueryableCapabilityAndMaxSize(),
// generic parcelable marshaler (MUST BE LAST since it has lowest priority)
new MarshalQueryableParcelable(),
diff --git a/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableCapabilityAndMaxSize.java b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableCapabilityAndMaxSize.java
new file mode 100644
index 0000000..5c1f301
--- /dev/null
+++ b/core/java/android/hardware/camera2/marshal/impl/MarshalQueryableCapabilityAndMaxSize.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.marshal.impl;
+
+import android.hardware.camera2.marshal.MarshalQueryable;
+import android.hardware.camera2.marshal.Marshaler;
+import android.hardware.camera2.params.CapabilityAndMaxSize;
+import android.hardware.camera2.utils.TypeReference;
+import android.util.Size;
+
+import java.nio.ByteBuffer;
+
+import static android.hardware.camera2.impl.CameraMetadataNative.TYPE_INT32;
+import static android.hardware.camera2.marshal.MarshalHelpers.SIZEOF_INT32;
+
+/**
+ * Marshal {@link CapabilityAndMaxSize} to/from {@link #TYPE_INT32} {@code x CapabilityAndMaxSize.COUNT}
+ */
+public class MarshalQueryableCapabilityAndMaxSize implements MarshalQueryable<CapabilityAndMaxSize> {
+ private static final int SIZE = SIZEOF_INT32 * CapabilityAndMaxSize.COUNT;
+
+ private class MarshalerCapabilityAndMaxSize extends Marshaler<CapabilityAndMaxSize> {
+ protected MarshalerCapabilityAndMaxSize(TypeReference<CapabilityAndMaxSize> typeReference,
+ int nativeType) {
+ super(MarshalQueryableCapabilityAndMaxSize.this, typeReference, nativeType);
+ }
+
+ @Override
+ public void marshal(CapabilityAndMaxSize value, ByteBuffer buffer) {
+ Size maxStreamingSize = value.getMaxStreamingSize();
+
+ buffer.putInt(value.getMode());
+ buffer.putInt(maxStreamingSize.getWidth());
+ buffer.putInt(maxStreamingSize.getHeight());
+ }
+
+ @Override
+ public CapabilityAndMaxSize unmarshal(ByteBuffer buffer) {
+ int mode = buffer.getInt();
+ int maxWidth = buffer.getInt();
+ int maxHeight = buffer.getInt();
+
+ return new CapabilityAndMaxSize(mode, maxWidth, maxHeight);
+ }
+
+ @Override
+ public int getNativeSize() {
+ return SIZE;
+ }
+ }
+
+ @Override
+ public Marshaler<CapabilityAndMaxSize> createMarshaler(
+ TypeReference<CapabilityAndMaxSize> managedType, int nativeType) {
+ return new MarshalerCapabilityAndMaxSize(managedType, nativeType);
+ }
+
+ @Override
+ public boolean isTypeMappingSupported(
+ TypeReference<CapabilityAndMaxSize> managedType, int nativeType) {
+ return nativeType == TYPE_INT32 &&
+ (CapabilityAndMaxSize.class.equals(managedType.getType()));
+ }
+}
diff --git a/core/java/android/hardware/camera2/params/CapabilityAndMaxSize.java b/core/java/android/hardware/camera2/params/CapabilityAndMaxSize.java
new file mode 100644
index 0000000..be08299
--- /dev/null
+++ b/core/java/android/hardware/camera2/params/CapabilityAndMaxSize.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.params;
+
+import static com.android.internal.util.Preconditions.checkArgumentInRange;
+import static com.android.internal.util.Preconditions.checkArgumentNonnegative;
+
+import android.annotation.NonNull;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.utils.HashCodeHelpers;
+import android.util.Size;
+
+/**
+ * Immutable class to store the available camera capability and its
+ * corresponding maximum streaming dimensions.
+ *
+ * @see CameraCharacteristics#CONTROL_AVAILABLE_BOKEH_CAPABILITIES
+ */
+
+public final class CapabilityAndMaxSize {
+ /**
+ * @hide
+ */
+ public static final int COUNT = 3;
+
+ private final int mMode;
+ private final int mMaxStreamingWidth;
+ private final int mMaxStreamingHeight;
+
+ /**
+ * Create a new CapabilityAndMaxSize object.
+ *
+ * @param mode supported mode for a camera capability.
+ * @param maxStreamingWidth width >= 0
+ * @param maxStreamingHeight height >= 0
+ *
+ * @hide
+ */
+ public CapabilityAndMaxSize(int mode, int maxStreamingWidth, int maxStreamingHeight) {
+ mMode = mode;
+ mMaxStreamingWidth = checkArgumentNonnegative(maxStreamingWidth,
+ "maxStreamingWidth must be nonnegative");
+ mMaxStreamingHeight = checkArgumentNonnegative(maxStreamingHeight,
+ "maxStreamingHeight must be nonnegative");
+ }
+
+ /**
+ * Return the supported mode for this capability.
+ *
+ * @return One of supported modes for the capability. For example, for available bokeh modes,
+ * this will be one of {@link CameraMetadata#CONTROL_BOKEH_MODE_OFF},
+ * {@link CameraMetadata#CONTROL_BOKEH_MODE_STILL_CAPTURE}, and
+ * {@link CameraMetadata#CONTROL_BOKEH_MODE_CONTINUOUS}.
+ */
+ public int getMode() {
+ return mMode;
+ }
+
+ /**
+ * Return the maximum streaming dimension of this capability.
+ *
+ * @return a new {@link Size} with non-negative width and height
+ */
+ public @NonNull Size getMaxStreamingSize() {
+ return new Size(mMaxStreamingWidth, mMaxStreamingHeight);
+ }
+
+ /**
+ * Compare two CapabilityAndMaxSize objects to see if they are equal.
+ *
+ * @param obj Another CapabilityAndMaxSize object
+ *
+ * @return {@code true} if the mode and max size are equal, {@code false} otherwise
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof CapabilityAndMaxSize) {
+ final CapabilityAndMaxSize other = (CapabilityAndMaxSize) obj;
+ return (mMode == other.mMode
+ && mMaxStreamingWidth == other.mMaxStreamingWidth
+ && mMaxStreamingHeight == other.mMaxStreamingHeight);
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return HashCodeHelpers.hashCode(mMode, mMaxStreamingWidth, mMaxStreamingHeight);
+ }
+
+ /**
+ * Return the CapabilityAndMaxSize as a string representation
+ * {@code "(mode:%d, maxStreamingSize:%d x %d)"}.
+ *
+ * @return string representation of the capability and max streaming size.
+ */
+ @Override
+ public String toString() {
+ return String.format("(mode:%d, maxStreamingSize:%d x %d)",
+ mMode, mMaxStreamingWidth, mMaxStreamingHeight);
+ }
+}
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index 535bf67..64f20b8 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -49,8 +49,8 @@
* limited to a local network over Multicast DNS. DNS service discovery is described at
* http://files.dns-sd.org/draft-cheshire-dnsext-dns-sd.txt
*
- * <p> The API is asynchronous and responses to requests from an application are on listener
- * callbacks on a seperate internal thread.
+ * <p> The API is asynchronous, and responses to requests from an application are on listener
+ * callbacks on a separate internal thread.
*
* <p> There are three main operations the API supports - registration, discovery and resolution.
* <pre>
diff --git a/core/java/android/net/util/SocketUtils.java b/core/java/android/net/util/SocketUtils.java
index 489a292..e9ea99f 100644
--- a/core/java/android/net/util/SocketUtils.java
+++ b/core/java/android/net/util/SocketUtils.java
@@ -77,7 +77,9 @@
/**
* Make a socket address that packet socket can send packets to.
+ * @deprecated Use {@link #makePacketSocketAddress(int, int, byte[])} instead.
*/
+ @Deprecated
@NonNull
public static SocketAddress makePacketSocketAddress(int ifIndex, @NonNull byte[] hwAddr) {
return new PacketSocketAddress(
@@ -87,6 +89,18 @@
}
/**
+ * Make a socket address that packet socket can send packets to.
+ */
+ @NonNull
+ public static SocketAddress makePacketSocketAddress(int protocol, int ifIndex,
+ @NonNull byte[] hwAddr) {
+ return new PacketSocketAddress(
+ protocol /* sll_protocol */,
+ ifIndex /* sll_ifindex */,
+ hwAddr /* sll_addr */);
+ }
+
+ /**
* @see IoBridge#closeAndSignalBlockedThreads(FileDescriptor)
*/
public static void closeSocket(@Nullable FileDescriptor fd) throws IOException {
diff --git a/core/java/android/os/BasicShellCommandHandler.java b/core/java/android/os/BasicShellCommandHandler.java
new file mode 100644
index 0000000..5bd5d61
--- /dev/null
+++ b/core/java/android/os/BasicShellCommandHandler.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+/**
+ * Helper for implementing {@link Binder#onShellCommand Binder.onShellCommand}. This is meant to
+ * be copied into mainline modules, so this class must not use any hidden APIs.
+ *
+ * @hide
+ */
+public abstract class BasicShellCommandHandler {
+ static final String TAG = "ShellCommand";
+ static final boolean DEBUG = false;
+
+ private Binder mTarget;
+ private FileDescriptor mIn;
+ private FileDescriptor mOut;
+ private FileDescriptor mErr;
+ private String[] mArgs;
+
+ private String mCmd;
+ private int mArgPos;
+ private String mCurArgData;
+
+ private FileInputStream mFileIn;
+ private FileOutputStream mFileOut;
+ private FileOutputStream mFileErr;
+
+ private PrintWriter mOutPrintWriter;
+ private PrintWriter mErrPrintWriter;
+ private InputStream mInputStream;
+
+ public void init(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args, int firstArgPos) {
+ mTarget = target;
+ mIn = in;
+ mOut = out;
+ mErr = err;
+ mArgs = args;
+ mCmd = null;
+ mArgPos = firstArgPos;
+ mCurArgData = null;
+ mFileIn = null;
+ mFileOut = null;
+ mFileErr = null;
+ mOutPrintWriter = null;
+ mErrPrintWriter = null;
+ mInputStream = null;
+ }
+
+ public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
+ String[] args) {
+ String cmd;
+ int start;
+ if (args != null && args.length > 0) {
+ cmd = args[0];
+ start = 1;
+ } else {
+ cmd = null;
+ start = 0;
+ }
+ init(target, in, out, err, args, start);
+ mCmd = cmd;
+
+ if (DEBUG) {
+ RuntimeException here = new RuntimeException("here");
+ here.fillInStackTrace();
+ Log.d(TAG, "Starting command " + mCmd + " on " + mTarget, here);
+ Log.d(TAG, "Calling uid=" + Binder.getCallingUid()
+ + " pid=" + Binder.getCallingPid());
+ }
+ int res = -1;
+ try {
+ res = onCommand(mCmd);
+ if (DEBUG) Log.d(TAG, "Executed command " + mCmd + " on " + mTarget);
+ } catch (Throwable e) {
+ // Unlike usual calls, in this case if an exception gets thrown
+ // back to us we want to print it back in to the dump data, since
+ // that is where the caller expects all interesting information to
+ // go.
+ PrintWriter eout = getErrPrintWriter();
+ eout.println();
+ eout.println("Exception occurred while executing: " + e.getMessage());
+ e.printStackTrace(eout);
+ } finally {
+ if (DEBUG) Log.d(TAG, "Flushing output streams on " + mTarget);
+ if (mOutPrintWriter != null) {
+ mOutPrintWriter.flush();
+ }
+ if (mErrPrintWriter != null) {
+ mErrPrintWriter.flush();
+ }
+ if (DEBUG) Log.d(TAG, "Sending command result on " + mTarget);
+ }
+ if (DEBUG) Log.d(TAG, "Finished command " + mCmd + " on " + mTarget);
+ return res;
+ }
+
+ /**
+ * Return the raw FileDescriptor for the output stream.
+ */
+ public FileDescriptor getOutFileDescriptor() {
+ return mOut;
+ }
+
+ /**
+ * Return direct raw access (not buffered) to the command's output data stream.
+ */
+ public OutputStream getRawOutputStream() {
+ if (mFileOut == null) {
+ mFileOut = new FileOutputStream(mOut);
+ }
+ return mFileOut;
+ }
+
+ /**
+ * Return a PrintWriter for formatting output to {@link #getRawOutputStream()}.
+ */
+ public PrintWriter getOutPrintWriter() {
+ if (mOutPrintWriter == null) {
+ mOutPrintWriter = new PrintWriter(getRawOutputStream());
+ }
+ return mOutPrintWriter;
+ }
+
+ /**
+ * Return the raw FileDescriptor for the error stream.
+ */
+ public FileDescriptor getErrFileDescriptor() {
+ return mErr;
+ }
+
+ /**
+ * Return direct raw access (not buffered) to the command's error output data stream.
+ */
+ public OutputStream getRawErrorStream() {
+ if (mFileErr == null) {
+ mFileErr = new FileOutputStream(mErr);
+ }
+ return mFileErr;
+ }
+
+ /**
+ * Return a PrintWriter for formatting output to {@link #getRawErrorStream()}.
+ */
+ public PrintWriter getErrPrintWriter() {
+ if (mErr == null) {
+ return getOutPrintWriter();
+ }
+ if (mErrPrintWriter == null) {
+ mErrPrintWriter = new PrintWriter(getRawErrorStream());
+ }
+ return mErrPrintWriter;
+ }
+
+ /**
+ * Return the raw FileDescriptor for the input stream.
+ */
+ public FileDescriptor getInFileDescriptor() {
+ return mIn;
+ }
+
+ /**
+ * Return direct raw access (not buffered) to the command's input data stream.
+ */
+ public InputStream getRawInputStream() {
+ if (mFileIn == null) {
+ mFileIn = new FileInputStream(mIn);
+ }
+ return mFileIn;
+ }
+
+ /**
+ * Return buffered access to the command's {@link #getRawInputStream()}.
+ */
+ public InputStream getBufferedInputStream() {
+ if (mInputStream == null) {
+ mInputStream = new BufferedInputStream(getRawInputStream());
+ }
+ return mInputStream;
+ }
+
+ /**
+ * Return the next option on the command line -- that is an argument that
+ * starts with '-'. If the next argument is not an option, null is returned.
+ */
+ public String getNextOption() {
+ if (mCurArgData != null) {
+ String prev = mArgs[mArgPos - 1];
+ throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
+ }
+ if (mArgPos >= mArgs.length) {
+ return null;
+ }
+ String arg = mArgs[mArgPos];
+ if (!arg.startsWith("-")) {
+ return null;
+ }
+ mArgPos++;
+ if (arg.equals("--")) {
+ return null;
+ }
+ if (arg.length() > 1 && arg.charAt(1) != '-') {
+ if (arg.length() > 2) {
+ mCurArgData = arg.substring(2);
+ return arg.substring(0, 2);
+ } else {
+ mCurArgData = null;
+ return arg;
+ }
+ }
+ mCurArgData = null;
+ return arg;
+ }
+
+ /**
+ * Return the next argument on the command line, whatever it is; if there are
+ * no arguments left, return null.
+ */
+ public String getNextArg() {
+ if (mCurArgData != null) {
+ String arg = mCurArgData;
+ mCurArgData = null;
+ return arg;
+ } else if (mArgPos < mArgs.length) {
+ return mArgs[mArgPos++];
+ } else {
+ return null;
+ }
+ }
+
+ public String peekNextArg() {
+ if (mCurArgData != null) {
+ return mCurArgData;
+ } else if (mArgPos < mArgs.length) {
+ return mArgs[mArgPos];
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Return the next argument on the command line, whatever it is; if there are
+ * no arguments left, throws an IllegalArgumentException to report this to the user.
+ */
+ public String getNextArgRequired() {
+ String arg = getNextArg();
+ if (arg == null) {
+ String prev = mArgs[mArgPos - 1];
+ throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
+ }
+ return arg;
+ }
+
+ public int handleDefaultCommands(String cmd) {
+ if (cmd == null || "help".equals(cmd) || "-h".equals(cmd)) {
+ onHelp();
+ } else {
+ getOutPrintWriter().println("Unknown command: " + cmd);
+ }
+ return -1;
+ }
+
+ public Binder getTarget() {
+ return mTarget;
+ }
+
+ public String[] getAllArgs() {
+ return mArgs;
+ }
+
+ /**
+ * Implement parsing and execution of a command. If it isn't a command you understand,
+ * call {@link #handleDefaultCommands(String)} and return its result as a last resort.
+ * Use {@link #getNextOption()}, {@link #getNextArg()}, and {@link #getNextArgRequired()}
+ * to process additional command line arguments. Command output can be written to
+ * {@link #getOutPrintWriter()} and errors to {@link #getErrPrintWriter()}.
+ *
+ * <p class="caution">Note that no permission checking has been done before entering this
+ * function, so you need to be sure to do your own security verification for any commands you
+ * are executing. The easiest way to do this is to have the ShellCommand contain
+ * only a reference to your service's aidl interface, and do all of your command
+ * implementations on top of that -- that way you can rely entirely on your executing security
+ * code behind that interface.</p>
+ *
+ * @param cmd The first command line argument representing the name of the command to execute.
+ * @return Return the command result; generally 0 or positive indicates success and
+ * negative values indicate error.
+ */
+ public abstract int onCommand(String cmd);
+
+ /**
+ * Implement this to print help text about your command to {@link #getOutPrintWriter()}.
+ */
+ public abstract void onHelp();
+}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index af0ec11..3ae1fe6 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -17,11 +17,11 @@
package android.os;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
-import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION;
import android.annotation.IntDef;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityManager;
+import android.app.job.JobParameters;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.server.ServerProtoEnums;
@@ -45,7 +45,6 @@
import com.android.internal.location.gnssmetrics.GnssMetrics;
import com.android.internal.os.BatterySipper;
import com.android.internal.os.BatteryStatsHelper;
-import com.android.internal.util.Preconditions;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -59,7 +58,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.function.Function;
/**
* A class providing access to battery usage statistics, including information on
@@ -420,40 +418,6 @@
};
/**
- * "Job stop reason codes" from the job scheduler subsystem, which we can't refer to from this
- * class, so we initialize it from the job scheduler side at runtime using
- * {@link #setJobStopReasons}.
- */
- private static int[] sJobStopReasonCodes = {0};
-
- /**
- * A function that converts the "job stop reason codes" to their names.
- *
- * Similarly to {@link #sJobStopReasonCodes} it's initialized by the job scheduler subsystem
- * using {@link #setJobStopReasons}.
- */
- private static Function<Integer, String> sJobStopReasonNameConverter = (x) -> "unknown";
-
- /**
- * Set by the job scheduler subsystem to "push" job stop reasons, and a function that returns
- * the "name" of each code. We do it this way to remove a build time dependency from this
- * class to the job scheduler framework code.
- *
- * Note the passed array will be used as-is, without copying. The caller must not change
- * the array it passed to it.
- *
- * @hide
- */
- public static void setJobStopReasons(int[] reasonCodes,
- Function<Integer, String> jobStopReasonNameConverter) {
- Preconditions.checkArgument(reasonCodes.length > 0);
- Preconditions.checkArgument(jobStopReasonNameConverter != null);
-
- sJobStopReasonCodes = reasonCodes;
- sJobStopReasonNameConverter = jobStopReasonNameConverter;
- }
-
- /**
* State for keeping track of counting information.
*/
public static abstract class Counter {
@@ -923,7 +887,6 @@
*/
public static final int[] CRITICAL_PROC_STATES = {
PROCESS_STATE_TOP,
- PROCESS_STATE_FOREGROUND_SERVICE_LOCATION,
PROCESS_STATE_BOUND_TOP, PROCESS_STATE_FOREGROUND_SERVICE,
PROCESS_STATE_FOREGROUND
};
@@ -4341,15 +4304,16 @@
}
}
- final Object[] jobCompletionArgs = new Object[sJobStopReasonCodes.length + 1];
+ final int[] jobStopReasonCodes = JobParameters.getJobStopReasonCodes();
+ final Object[] jobCompletionArgs = new Object[jobStopReasonCodes.length + 1];
final ArrayMap<String, SparseIntArray> completions = u.getJobCompletionStats();
for (int ic=completions.size()-1; ic>=0; ic--) {
SparseIntArray types = completions.valueAt(ic);
if (types != null) {
jobCompletionArgs[0] = "\"" + completions.keyAt(ic) + "\"";
- for (int i = 0; i < sJobStopReasonCodes.length; i++) {
- jobCompletionArgs[i + 1] = types.get(sJobStopReasonCodes[i], 0);
+ for (int i = 0; i < jobStopReasonCodes.length; i++) {
+ jobCompletionArgs[i + 1] = types.get(jobStopReasonCodes[i], 0);
}
dumpLine(pw, uid, category, JOB_COMPLETION_DATA, jobCompletionArgs);
@@ -5969,7 +5933,7 @@
pw.print(":");
for (int it=0; it<types.size(); it++) {
pw.print(" ");
- pw.print(sJobStopReasonNameConverter.apply(types.keyAt(it)));
+ pw.print(JobParameters.getReasonCodeDescription(types.keyAt(it)));
pw.print("(");
pw.print(types.valueAt(it));
pw.print("x)");
@@ -7567,7 +7531,7 @@
proto.write(UidProto.JobCompletion.NAME, completions.keyAt(ic));
- for (int r : sJobStopReasonCodes) {
+ for (int r : JobParameters.getJobStopReasonCodes()) {
long rToken = proto.start(UidProto.JobCompletion.REASON_COUNT);
proto.write(UidProto.JobCompletion.ReasonCount.NAME, r);
proto.write(UidProto.JobCompletion.ReasonCount.COUNT, types.get(r, 0));
diff --git a/core/java/android/os/BatteryStatsManager.java b/core/java/android/os/BatteryStatsManager.java
index 367a868..e5650ae 100644
--- a/core/java/android/os/BatteryStatsManager.java
+++ b/core/java/android/os/BatteryStatsManager.java
@@ -23,6 +23,7 @@
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
+import android.os.connectivity.CellularBatteryStats;
import android.os.connectivity.WifiBatteryStats;
import com.android.internal.app.IBatteryStats;
@@ -158,6 +159,21 @@
}
/**
+ * Retrieves all the cellular related battery stats.
+ *
+ * @return Instance of {@link CellularBatteryStats}.
+ */
+ @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
+ public @NonNull CellularBatteryStats getCellularBatteryStats() {
+ try {
+ return mBatteryStats.getCellularBatteryStats();
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ return null;
+ }
+ }
+
+ /**
* Retrieves all the wifi related battery stats.
*
* @return Instance of {@link WifiBatteryStats}.
diff --git a/core/java/android/os/Binder.java b/core/java/android/os/Binder.java
index ef3afab..fda1539 100644
--- a/core/java/android/os/Binder.java
+++ b/core/java/android/os/Binder.java
@@ -37,7 +37,9 @@
import libcore.util.NativeAllocationRegistry;
import java.io.FileDescriptor;
+import java.io.FileInputStream;
import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Modifier;
@@ -905,11 +907,62 @@
@Nullable FileDescriptor err,
@NonNull String[] args, @Nullable ShellCallback callback,
@NonNull ResultReceiver resultReceiver) throws RemoteException {
- FileOutputStream fout = new FileOutputStream(err != null ? err : out);
- PrintWriter pw = new FastPrintWriter(fout);
+
+ // First, convert in, out and err to @NonNull, by redirecting any that's null to /dev/null.
+ try {
+ if (in == null) {
+ in = new FileInputStream("/dev/null").getFD();
+ }
+ if (out == null) {
+ out = new FileOutputStream("/dev/null").getFD();
+ }
+ if (err == null) {
+ err = out;
+ }
+ } catch (IOException e) {
+ PrintWriter pw = new FastPrintWriter(new FileOutputStream(err != null ? err : out));
+ pw.println("Failed to open /dev/null: " + e.getMessage());
+ pw.flush();
+ resultReceiver.send(-1, null);
+ return;
+ }
+ // Also make args @NonNull.
+ if (args == null) {
+ args = new String[0];
+ }
+
+ int result = -1;
+ try {
+ result = handleShellCommand(new ParcelFileDescriptor(in),
+ new ParcelFileDescriptor(out), new ParcelFileDescriptor(err), args);
+ } finally {
+ resultReceiver.send(result, null);
+ }
+ }
+
+ /**
+ * System services can implement this method to implement ADB shell commands.
+ *
+ * TODO More Javadoc.
+ * TODO Add a generic way to define subcommands and their permissions.
+ *
+ * @param in standard input.
+ * @param out standard output.
+ * @param err standard error.
+ * @param args arguments passed to the command. Can be empty. The first argument is typically
+ * a subcommand, such as {@code run} for {@code adb shell cmd jobscheduler run}.
+ *
+ * @hide
+ */
+ // @SystemApi TODO Make it a system API.
+ protected int handleShellCommand(@NonNull ParcelFileDescriptor in,
+ @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
+ @NonNull String[] args) {
+ FileOutputStream ferr = new FileOutputStream(err.getFileDescriptor());
+ PrintWriter pw = new FastPrintWriter(ferr);
pw.println("No shell command implementation.");
pw.flush();
- resultReceiver.send(0, null);
+ return 0;
}
/**
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index b3b4f78..ee95fce 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -242,32 +242,37 @@
}
Map<String, Integer> counts = new HashMap<>();
- for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
- if (a != null) {
- for (WeakReference<BinderProxy> weakRef : a) {
- BinderProxy bp = weakRef.get();
- String key;
- if (bp == null) {
- key = "<cleared weak-ref>";
- } else {
- try {
- key = bp.getInterfaceDescriptor();
- if ((key == null || key.isEmpty()) && !bp.isBinderAlive()) {
- key = "<proxy to dead node>";
- }
- } catch (Throwable t) {
- key = "<exception during getDescriptor>";
- }
- }
- Integer i = counts.get(key);
- if (i == null) {
- counts.put(key, 1);
- } else {
- counts.put(key, i + 1);
- }
+ final ArrayList<WeakReference<BinderProxy>> proxiesToQuery =
+ new ArrayList<WeakReference<BinderProxy>>();
+ synchronized (sProxyMap) {
+ for (ArrayList<WeakReference<BinderProxy>> a : mMainIndexValues) {
+ if (a != null) {
+ proxiesToQuery.addAll(a);
}
}
}
+ for (WeakReference<BinderProxy> weakRef : proxiesToQuery) {
+ BinderProxy bp = weakRef.get();
+ String key;
+ if (bp == null) {
+ key = "<cleared weak-ref>";
+ } else {
+ try {
+ key = bp.getInterfaceDescriptor();
+ if ((key == null || key.isEmpty()) && !bp.isBinderAlive()) {
+ key = "<proxy to dead node>";
+ }
+ } catch (Throwable t) {
+ key = "<exception during getDescriptor>";
+ }
+ }
+ Integer i = counts.get(key);
+ if (i == null) {
+ counts.put(key, 1);
+ } else {
+ counts.put(key, i + 1);
+ }
+ }
Map.Entry<String, Integer>[] sorted = counts.entrySet().toArray(
new Map.Entry[counts.size()]);
@@ -355,9 +360,7 @@
* @hide
*/
public static InterfaceCount[] getSortedInterfaceCounts(int num) {
- synchronized (sProxyMap) {
- return sProxyMap.getSortedInterfaceCounts(num);
- }
+ return sProxyMap.getSortedInterfaceCounts(num);
}
/**
@@ -377,10 +380,8 @@
*/
public static void dumpProxyDebugInfo() {
if (Build.IS_DEBUGGABLE) {
- synchronized (sProxyMap) {
- sProxyMap.dumpProxyInterfaceCounts();
- sProxyMap.dumpPerUidProxyCounts();
- }
+ sProxyMap.dumpProxyInterfaceCounts();
+ sProxyMap.dumpPerUidProxyCounts();
}
}
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index bc32df4..5634929 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -1754,6 +1754,8 @@
* such runtime statistic exists.
*
* <p>The following table lists the runtime statistics that the runtime supports.
+ * All statistics are approximate. Individual allocations may not be immediately reflected
+ * in the results.
* Note runtime statistics may be added or removed in a future API level.</p>
*
* <table>
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 794d62e..dd1f8c3 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -37,7 +37,6 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.Executor;
-import java.util.function.Function;
/**
* This class gives you control of the power state of the device.
@@ -828,13 +827,13 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
final Handler mHandler;
+ /** We lazily initialize it.*/
+ private DeviceIdleManager mDeviceIdleManager;
+
IThermalService mThermalService;
private final ArrayMap<OnThermalStatusChangedListener, IThermalStatusListener>
mListenerMap = new ArrayMap<>();
- private static Function<String, Boolean> sIsIgnoringBatteryOptimizationsCallback =
- (packageName) -> false;
-
/**
* {@hide}
*/
@@ -844,6 +843,14 @@
mHandler = handler;
}
+ private DeviceIdleManager getDeviceIdleManager() {
+ if (mDeviceIdleManager == null) {
+ // No need for synchronization; getSystemService() will return the same object anyway.
+ mDeviceIdleManager = mContext.getSystemService(DeviceIdleManager.class);
+ }
+ return mDeviceIdleManager;
+ }
+
/**
* Gets the minimum supported screen brightness setting.
* The screen may be allowed to become dimmer than this value but
@@ -1662,12 +1669,7 @@
* {@link android.provider.Settings#ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS}.
*/
public boolean isIgnoringBatteryOptimizations(String packageName) {
- return sIsIgnoringBatteryOptimizationsCallback.apply(packageName);
- }
-
- /** @hide */
- public static void setIsIgnoringBatteryOptimizationsCallback(Function<String, Boolean> f) {
- sIsIgnoringBatteryOptimizationsCallback = f;
+ return getDeviceIdleManager().isApplicationWhitelisted(packageName);
}
/**
diff --git a/core/java/android/os/ShellCommand.java b/core/java/android/os/ShellCommand.java
index 2fe8726..f3a6869 100644
--- a/core/java/android/os/ShellCommand.java
+++ b/core/java/android/os/ShellCommand.java
@@ -33,105 +33,21 @@
* Helper for implementing {@link Binder#onShellCommand Binder.onShellCommand}.
* @hide
*/
-public abstract class ShellCommand {
- static final String TAG = "ShellCommand";
- static final boolean DEBUG = false;
-
- private Binder mTarget;
- private FileDescriptor mIn;
- private FileDescriptor mOut;
- private FileDescriptor mErr;
- private String[] mArgs;
+public abstract class ShellCommand extends BasicShellCommandHandler {
private ShellCallback mShellCallback;
private ResultReceiver mResultReceiver;
- private String mCmd;
- private int mArgPos;
- private String mCurArgData;
-
- private FileInputStream mFileIn;
- private FileOutputStream mFileOut;
- private FileOutputStream mFileErr;
-
- private FastPrintWriter mOutPrintWriter;
- private FastPrintWriter mErrPrintWriter;
- private InputStream mInputStream;
-
- public void init(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ShellCallback callback, int firstArgPos) {
- mTarget = target;
- mIn = in;
- mOut = out;
- mErr = err;
- mArgs = args;
- mShellCallback = callback;
- mResultReceiver = null;
- mCmd = null;
- mArgPos = firstArgPos;
- mCurArgData = null;
- mFileIn = null;
- mFileOut = null;
- mFileErr = null;
- mOutPrintWriter = null;
- mErrPrintWriter = null;
- mInputStream = null;
- }
-
public int exec(Binder target, FileDescriptor in, FileDescriptor out, FileDescriptor err,
String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
- String cmd;
- int start;
- if (args != null && args.length > 0) {
- cmd = args[0];
- start = 1;
- } else {
- cmd = null;
- start = 0;
- }
- init(target, in, out, err, args, callback, start);
- mCmd = cmd;
+ mShellCallback = callback;
mResultReceiver = resultReceiver;
+ final int result = super.exec(target, in, out, err, args);
- if (DEBUG) {
- RuntimeException here = new RuntimeException("here");
- here.fillInStackTrace();
- Slog.d(TAG, "Starting command " + mCmd + " on " + mTarget, here);
- Slog.d(TAG, "Calling uid=" + Binder.getCallingUid()
- + " pid=" + Binder.getCallingPid() + " ShellCallback=" + getShellCallback());
+ if (mResultReceiver != null) {
+ mResultReceiver.send(result, null);
}
- int res = -1;
- try {
- res = onCommand(mCmd);
- if (DEBUG) Slog.d(TAG, "Executed command " + mCmd + " on " + mTarget);
- } catch (SecurityException e) {
- PrintWriter eout = getErrPrintWriter();
- eout.println("Security exception: " + e.getMessage());
- eout.println();
- e.printStackTrace(eout);
- } catch (Throwable e) {
- // Unlike usual calls, in this case if an exception gets thrown
- // back to us we want to print it back in to the dump data, since
- // that is where the caller expects all interesting information to
- // go.
- PrintWriter eout = getErrPrintWriter();
- eout.println();
- eout.println("Exception occurred while executing:");
- e.printStackTrace(eout);
- } finally {
- if (DEBUG) Slog.d(TAG, "Flushing output streams on " + mTarget);
- if (mOutPrintWriter != null) {
- mOutPrintWriter.flush();
- }
- if (mErrPrintWriter != null) {
- mErrPrintWriter.flush();
- }
- if (DEBUG) Slog.d(TAG, "Sending command result on " + mTarget);
- if (mResultReceiver != null) {
- mResultReceiver.send(res, null);
- }
- }
- if (DEBUG) Slog.d(TAG, "Finished command " + mCmd + " on " + mTarget);
- return res;
+
+ return result;
}
/**
@@ -146,90 +62,6 @@
}
/**
- * Return the raw FileDescriptor for the output stream.
- */
- public FileDescriptor getOutFileDescriptor() {
- return mOut;
- }
-
- /**
- * Return direct raw access (not buffered) to the command's output data stream.
- */
- public OutputStream getRawOutputStream() {
- if (mFileOut == null) {
- mFileOut = new FileOutputStream(mOut);
- }
- return mFileOut;
- }
-
- /**
- * Return a PrintWriter for formatting output to {@link #getRawOutputStream()}.
- */
- public PrintWriter getOutPrintWriter() {
- if (mOutPrintWriter == null) {
- mOutPrintWriter = new FastPrintWriter(getRawOutputStream());
- }
- return mOutPrintWriter;
- }
-
- /**
- * Return the raw FileDescriptor for the error stream.
- */
- public FileDescriptor getErrFileDescriptor() {
- return mErr;
- }
-
- /**
- * Return direct raw access (not buffered) to the command's error output data stream.
- */
- public OutputStream getRawErrorStream() {
- if (mFileErr == null) {
- mFileErr = new FileOutputStream(mErr);
- }
- return mFileErr;
- }
-
- /**
- * Return a PrintWriter for formatting output to {@link #getRawErrorStream()}.
- */
- public PrintWriter getErrPrintWriter() {
- if (mErr == null) {
- return getOutPrintWriter();
- }
- if (mErrPrintWriter == null) {
- mErrPrintWriter = new FastPrintWriter(getRawErrorStream());
- }
- return mErrPrintWriter;
- }
-
- /**
- * Return the raw FileDescriptor for the input stream.
- */
- public FileDescriptor getInFileDescriptor() {
- return mIn;
- }
-
- /**
- * Return direct raw access (not buffered) to the command's input data stream.
- */
- public InputStream getRawInputStream() {
- if (mFileIn == null) {
- mFileIn = new FileInputStream(mIn);
- }
- return mFileIn;
- }
-
- /**
- * Return buffered access to the command's {@link #getRawInputStream()}.
- */
- public InputStream getBufferedInputStream() {
- if (mInputStream == null) {
- mInputStream = new BufferedInputStream(getRawInputStream());
- }
- return mInputStream;
- }
-
- /**
* Helper for just system services to ask the shell to open an output file.
* @hide
*/
@@ -256,77 +88,19 @@
return null;
}
- /**
- * Return the next option on the command line -- that is an argument that
- * starts with '-'. If the next argument is not an option, null is returned.
- */
- public String getNextOption() {
- if (mCurArgData != null) {
- String prev = mArgs[mArgPos - 1];
- throw new IllegalArgumentException("No argument expected after \"" + prev + "\"");
+ public int handleDefaultCommands(String cmd) {
+ if ("dump".equals(cmd)) {
+ String[] newArgs = new String[getAllArgs().length-1];
+ System.arraycopy(getAllArgs(), 1, newArgs, 0, getAllArgs().length-1);
+ getTarget().doDump(getOutFileDescriptor(), getOutPrintWriter(), newArgs);
+ return 0;
}
- if (mArgPos >= mArgs.length) {
- return null;
- }
- String arg = mArgs[mArgPos];
- if (!arg.startsWith("-")) {
- return null;
- }
- mArgPos++;
- if (arg.equals("--")) {
- return null;
- }
- if (arg.length() > 1 && arg.charAt(1) != '-') {
- if (arg.length() > 2) {
- mCurArgData = arg.substring(2);
- return arg.substring(0, 2);
- } else {
- mCurArgData = null;
- return arg;
- }
- }
- mCurArgData = null;
- return arg;
- }
-
- /**
- * Return the next argument on the command line, whatever it is; if there are
- * no arguments left, return null.
- */
- public String getNextArg() {
- if (mCurArgData != null) {
- String arg = mCurArgData;
- mCurArgData = null;
- return arg;
- } else if (mArgPos < mArgs.length) {
- return mArgs[mArgPos++];
- } else {
- return null;
- }
+ return super.handleDefaultCommands(cmd);
}
@UnsupportedAppUsage
public String peekNextArg() {
- if (mCurArgData != null) {
- return mCurArgData;
- } else if (mArgPos < mArgs.length) {
- return mArgs[mArgPos];
- } else {
- return null;
- }
- }
-
- /**
- * Return the next argument on the command line, whatever it is; if there are
- * no arguments left, throws an IllegalArgumentException to report this to the user.
- */
- public String getNextArgRequired() {
- String arg = getNextArg();
- if (arg == null) {
- String prev = mArgs[mArgPos - 1];
- throw new IllegalArgumentException("Argument expected after \"" + prev + "\"");
- }
- return arg;
+ return super.peekNextArg();
}
/**
@@ -335,43 +109,4 @@
public ShellCallback getShellCallback() {
return mShellCallback;
}
-
- public int handleDefaultCommands(String cmd) {
- if ("dump".equals(cmd)) {
- String[] newArgs = new String[mArgs.length-1];
- System.arraycopy(mArgs, 1, newArgs, 0, mArgs.length-1);
- mTarget.doDump(mOut, getOutPrintWriter(), newArgs);
- return 0;
- } else if (cmd == null || "help".equals(cmd) || "-h".equals(cmd)) {
- onHelp();
- } else {
- getOutPrintWriter().println("Unknown command: " + cmd);
- }
- return -1;
- }
-
- /**
- * Implement parsing and execution of a command. If it isn't a command you understand,
- * call {@link #handleDefaultCommands(String)} and return its result as a last resort.
- * Use {@link #getNextOption()}, {@link #getNextArg()}, and {@link #getNextArgRequired()}
- * to process additional command line arguments. Command output can be written to
- * {@link #getOutPrintWriter()} and errors to {@link #getErrPrintWriter()}.
- *
- * <p class="caution">Note that no permission checking has been done before entering this function,
- * so you need to be sure to do your own security verification for any commands you
- * are executing. The easiest way to do this is to have the ShellCommand contain
- * only a reference to your service's aidl interface, and do all of your command
- * implementations on top of that -- that way you can rely entirely on your executing security
- * code behind that interface.</p>
- *
- * @param cmd The first command line argument representing the name of the command to execute.
- * @return Return the command result; generally 0 or positive indicates success and
- * negative values indicate error.
- */
- public abstract int onCommand(String cmd);
-
- /**
- * Implement this to print help text about your command to {@link #getOutPrintWriter()}.
- */
- public abstract void onHelp();
}
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index d4abf28..9d14d9d 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -151,6 +151,7 @@
* @hide
*/
@SystemApi
+ @TestApi
public static int getInt(@NonNull String key, int def) {
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get_int(key, def);
@@ -166,6 +167,7 @@
* @hide
*/
@SystemApi
+ @TestApi
public static long getLong(@NonNull String key, long def) {
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get_long(key, def);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index b7a3c8f..b096049 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -1909,7 +1909,14 @@
* Returns the user-wide restrictions imposed on the user specified by <code>userHandle</code>.
* @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
* @return a Bundle containing all the restrictions.
+ *
+ * <p>Requires {@code android.permission.MANAGE_USERS} or
+ * {@code android.permission.INTERACT_ACROSS_USERS}, otherwise specified {@link UserHandle user}
+ * must be the calling user or a managed profile associated with it.
*/
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.MANAGE_USERS,
+ android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
public Bundle getUserRestrictions(UserHandle userHandle) {
try {
return mService.getUserRestrictions(userHandle.getIdentifier());
@@ -2000,7 +2007,7 @@
* @return {@code true} if the current user has the given restriction, {@code false} otherwise.
*/
public boolean hasUserRestriction(String restrictionKey) {
- return hasUserRestriction(restrictionKey, Process.myUserHandle());
+ return hasUserRestrictionForUser(restrictionKey, Process.myUserHandle());
}
/**
@@ -2012,9 +2019,29 @@
*/
@UnsupportedAppUsage
public boolean hasUserRestriction(String restrictionKey, UserHandle userHandle) {
+ return hasUserRestrictionForUser(restrictionKey, userHandle);
+ }
+
+ /**
+ * Returns whether the given user has been disallowed from performing certain actions
+ * or setting certain settings.
+ * @param restrictionKey the string key representing the restriction
+ * @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
+ *
+ * <p>Requires {@code android.permission.MANAGE_USERS} or
+ * {@code android.permission.INTERACT_ACROSS_USERS}, otherwise specified {@link UserHandle user}
+ * must be the calling user or a managed profile associated with it.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.MANAGE_USERS,
+ android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional = true)
+ public boolean hasUserRestrictionForUser(@NonNull String restrictionKey,
+ @NonNull UserHandle userHandle) {
try {
- return mService.hasUserRestriction(restrictionKey,
- userHandle.getIdentifier());
+ return mService.hasUserRestriction(restrictionKey, userHandle.getIdentifier());
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
@@ -2459,6 +2486,8 @@
/**
* Return the number of users currently created on the device.
+ * <p>This API is not for use by third-party apps. It requires the {@code MANAGE_USERS}
+ * permission.</p>
*/
public int getUserCount() {
List<UserInfo> users = getUsers();
diff --git a/core/java/android/os/connectivity/CellularBatteryStats.java b/core/java/android/os/connectivity/CellularBatteryStats.java
index 2e09040..caa4068 100644
--- a/core/java/android/os/connectivity/CellularBatteryStats.java
+++ b/core/java/android/os/connectivity/CellularBatteryStats.java
@@ -15,241 +15,367 @@
*/
package android.os.connectivity;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.BatteryStats;
import android.os.Parcel;
import android.os.Parcelable;
-
+import android.telephony.Annotation.NetworkType;
import android.telephony.ModemActivityInfo;
import android.telephony.SignalStrength;
import java.util.Arrays;
+import java.util.Objects;
/**
* API for Cellular power stats
*
* @hide
*/
+@SystemApi
public final class CellularBatteryStats implements Parcelable {
- private long mLoggingDurationMs;
- private long mKernelActiveTimeMs;
- private long mNumPacketsTx;
- private long mNumBytesTx;
- private long mNumPacketsRx;
- private long mNumBytesRx;
- private long mSleepTimeMs;
- private long mIdleTimeMs;
- private long mRxTimeMs;
- private long mEnergyConsumedMaMs;
- private long[] mTimeInRatMs;
- private long[] mTimeInRxSignalStrengthLevelMs;
- private long[] mTxTimeMs;
- private long mMonitoredRailChargeConsumedMaMs;
+ private long mLoggingDurationMs = 0;
+ private long mKernelActiveTimeMs = 0;
+ private long mNumPacketsTx = 0;
+ private long mNumBytesTx = 0;
+ private long mNumPacketsRx = 0;
+ private long mNumBytesRx = 0;
+ private long mSleepTimeMs = 0;
+ private long mIdleTimeMs = 0;
+ private long mRxTimeMs = 0;
+ private long mEnergyConsumedMaMs = 0;
+ private long[] mTimeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
+ private long[] mTimeInRxSignalStrengthLevelMs =
+ new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
+ private long[] mTxTimeMs = new long[ModemActivityInfo.TX_POWER_LEVELS];
+ private long mMonitoredRailChargeConsumedMaMs = 0;
- public static final @android.annotation.NonNull Parcelable.Creator<CellularBatteryStats> CREATOR = new
- Parcelable.Creator<CellularBatteryStats>() {
- public CellularBatteryStats createFromParcel(Parcel in) {
- return new CellularBatteryStats(in);
- }
+ public static final @NonNull Parcelable.Creator<CellularBatteryStats> CREATOR =
+ new Parcelable.Creator<CellularBatteryStats>() {
+ public CellularBatteryStats createFromParcel(Parcel in) {
+ return new CellularBatteryStats(in);
+ }
- public CellularBatteryStats[] newArray(int size) {
- return new CellularBatteryStats[size];
- }
- };
+ public CellularBatteryStats[] newArray(int size) {
+ return new CellularBatteryStats[size];
+ }
+ };
- public CellularBatteryStats() {
- initialize();
- }
+ /** @hide **/
+ public CellularBatteryStats() {}
- public void writeToParcel(Parcel out, int flags) {
- out.writeLong(mLoggingDurationMs);
- out.writeLong(mKernelActiveTimeMs);
- out.writeLong(mNumPacketsTx);
- out.writeLong(mNumBytesTx);
- out.writeLong(mNumPacketsRx);
- out.writeLong(mNumBytesRx);
- out.writeLong(mSleepTimeMs);
- out.writeLong(mIdleTimeMs);
- out.writeLong(mRxTimeMs);
- out.writeLong(mEnergyConsumedMaMs);
- out.writeLongArray(mTimeInRatMs);
- out.writeLongArray(mTimeInRxSignalStrengthLevelMs);
- out.writeLongArray(mTxTimeMs);
- out.writeLong(mMonitoredRailChargeConsumedMaMs);
- }
+ @Override
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeLong(mLoggingDurationMs);
+ out.writeLong(mKernelActiveTimeMs);
+ out.writeLong(mNumPacketsTx);
+ out.writeLong(mNumBytesTx);
+ out.writeLong(mNumPacketsRx);
+ out.writeLong(mNumBytesRx);
+ out.writeLong(mSleepTimeMs);
+ out.writeLong(mIdleTimeMs);
+ out.writeLong(mRxTimeMs);
+ out.writeLong(mEnergyConsumedMaMs);
+ out.writeLongArray(mTimeInRatMs);
+ out.writeLongArray(mTimeInRxSignalStrengthLevelMs);
+ out.writeLongArray(mTxTimeMs);
+ out.writeLong(mMonitoredRailChargeConsumedMaMs);
+ }
- public void readFromParcel(Parcel in) {
- mLoggingDurationMs = in.readLong();
- mKernelActiveTimeMs = in.readLong();
- mNumPacketsTx = in.readLong();
- mNumBytesTx = in.readLong();
- mNumPacketsRx = in.readLong();
- mNumBytesRx = in.readLong();
- mSleepTimeMs = in.readLong();
- mIdleTimeMs = in.readLong();
- mRxTimeMs = in.readLong();
- mEnergyConsumedMaMs = in.readLong();
- in.readLongArray(mTimeInRatMs);
- in.readLongArray(mTimeInRxSignalStrengthLevelMs);
- in.readLongArray(mTxTimeMs);
- mMonitoredRailChargeConsumedMaMs = in.readLong();
- }
+ private void readFromParcel(Parcel in) {
+ mLoggingDurationMs = in.readLong();
+ mKernelActiveTimeMs = in.readLong();
+ mNumPacketsTx = in.readLong();
+ mNumBytesTx = in.readLong();
+ mNumPacketsRx = in.readLong();
+ mNumBytesRx = in.readLong();
+ mSleepTimeMs = in.readLong();
+ mIdleTimeMs = in.readLong();
+ mRxTimeMs = in.readLong();
+ mEnergyConsumedMaMs = in.readLong();
+ in.readLongArray(mTimeInRatMs);
+ in.readLongArray(mTimeInRxSignalStrengthLevelMs);
+ in.readLongArray(mTxTimeMs);
+ mMonitoredRailChargeConsumedMaMs = in.readLong();
+ }
- public long getLoggingDurationMs() {
- return mLoggingDurationMs;
- }
+ @Override
+ public boolean equals(@Nullable Object other) {
+ if (!(other instanceof CellularBatteryStats)) return false;
+ if (other == this) return true;
+ CellularBatteryStats otherStats = (CellularBatteryStats) other;
+ return this.mLoggingDurationMs == otherStats.mLoggingDurationMs
+ && this.mKernelActiveTimeMs == otherStats.mKernelActiveTimeMs
+ && this.mNumPacketsTx == otherStats.mNumPacketsTx
+ && this.mNumBytesTx == otherStats.mNumBytesTx
+ && this.mNumPacketsRx == otherStats.mNumPacketsRx
+ && this.mNumBytesRx == otherStats.mNumBytesRx
+ && this.mSleepTimeMs == otherStats.mSleepTimeMs
+ && this.mIdleTimeMs == otherStats.mIdleTimeMs
+ && this.mRxTimeMs == otherStats.mRxTimeMs
+ && this.mEnergyConsumedMaMs == otherStats.mEnergyConsumedMaMs
+ && Arrays.equals(this.mTimeInRatMs, otherStats.mTimeInRatMs)
+ && Arrays.equals(this.mTimeInRxSignalStrengthLevelMs,
+ otherStats.mTimeInRxSignalStrengthLevelMs)
+ && Arrays.equals(this.mTxTimeMs, otherStats.mTxTimeMs)
+ && this.mMonitoredRailChargeConsumedMaMs
+ == otherStats.mMonitoredRailChargeConsumedMaMs;
+ }
- public long getKernelActiveTimeMs() {
- return mKernelActiveTimeMs;
- }
+ @Override
+ public int hashCode() {
+ return Objects.hash(mLoggingDurationMs, mKernelActiveTimeMs, mNumPacketsTx,
+ mNumBytesTx, mNumPacketsRx, mNumBytesRx, mSleepTimeMs, mIdleTimeMs,
+ mRxTimeMs, mEnergyConsumedMaMs, Arrays.hashCode(mTimeInRatMs),
+ Arrays.hashCode(mTimeInRxSignalStrengthLevelMs), Arrays.hashCode(mTxTimeMs),
+ mMonitoredRailChargeConsumedMaMs);
+ }
- public long getNumPacketsTx() {
- return mNumPacketsTx;
- }
+ /**
+ * Returns the duration for which these cellular stats were collected.
+ *
+ * @return Duration of stats collection in milliseconds.
+ */
+ public long getLoggingDurationMillis() {
+ return mLoggingDurationMs;
+ }
- public long getNumBytesTx() {
- return mNumBytesTx;
- }
+ /**
+ * Returns the duration for which the kernel was active within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Duration of kernel active time in milliseconds.
+ */
+ public long getKernelActiveTimeMillis() {
+ return mKernelActiveTimeMs;
+ }
- public long getNumPacketsRx() {
- return mNumPacketsRx;
- }
+ /**
+ * Returns the number of packets transmitted over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Number of packets transmitted.
+ */
+ public long getNumPacketsTx() {
+ return mNumPacketsTx;
+ }
- public long getNumBytesRx() {
- return mNumBytesRx;
- }
+ /**
+ * Returns the number of packets received over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Number of packets received.
+ */
+ public long getNumBytesTx() {
+ return mNumBytesTx;
+ }
- public long getSleepTimeMs() {
- return mSleepTimeMs;
- }
+ /**
+ * Returns the number of bytes transmitted over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Number of bytes transmitted.
+ */
+ public long getNumPacketsRx() {
+ return mNumPacketsRx;
+ }
- public long getIdleTimeMs() {
- return mIdleTimeMs;
- }
+ /**
+ * Returns the number of bytes received over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Number of bytes received.
+ */
+ public long getNumBytesRx() {
+ return mNumBytesRx;
+ }
- public long getRxTimeMs() {
- return mRxTimeMs;
- }
+ /**
+ * Returns the duration for which the device was sleeping within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Duration of sleep time in milliseconds.
+ */
+ public long getSleepTimeMillis() {
+ return mSleepTimeMs;
+ }
- public long getEnergyConsumedMaMs() {
- return mEnergyConsumedMaMs;
- }
+ /**
+ * Returns the duration for which the device was idle within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Duration of idle time in milliseconds.
+ */
+ public long getIdleTimeMillis() {
+ return mIdleTimeMs;
+ }
- public long[] getTimeInRatMs() {
- return mTimeInRatMs;
- }
+ /**
+ * Returns the duration for which the device was receiving over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Duration of cellular reception time in milliseconds.
+ */
+ public long getRxTimeMillis() {
+ return mRxTimeMs;
+ }
- public long[] getTimeInRxSignalStrengthLevelMs() {
- return mTimeInRxSignalStrengthLevelMs;
- }
+ /**
+ * Returns an estimation of energy consumed by cellular chip within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Energy consumed in milli-ampere milliseconds (mAmS).
+ */
+ public long getEnergyConsumedMaMillis() {
+ return mEnergyConsumedMaMs;
+ }
- public long[] getTxTimeMs() {
- return mTxTimeMs;
- }
+ /**
+ * Returns the time in microseconds that the phone has been running with
+ * the given data connection.
+ *
+ * @return Amount of time phone spends in various Radio Access Technologies in microseconds.
+ * The index is {@link NetworkType}.
+ */
+ @NonNull
+ public long[] getTimeInRatMicros() {
+ return mTimeInRatMs;
+ }
- public long getMonitoredRailChargeConsumedMaMs() {
- return mMonitoredRailChargeConsumedMaMs;
- }
+ /**
+ * Returns the time in microseconds that the phone has been running with
+ * the given signal strength.
+ *
+ * @return Amount of time phone spends in various cellular rx signal strength levels
+ * in microseconds. The index is signal strength bin.
+ */
+ @NonNull
+ public long[] getTimeInRxSignalStrengthLevelMicros() {
+ return mTimeInRxSignalStrengthLevelMs;
+ }
- public void setLoggingDurationMs(long t) {
- mLoggingDurationMs = t;
- return;
- }
+ /**
+ * Returns the duration for which the device was transmitting over cellular within
+ * {@link #getLoggingDurationMillis()}.
+ *
+ * @return Duration of cellular transmission time in milliseconds.
+ * Tx(transmit) power index below
+ * <ul>
+ * <li> index 0 = tx_power < 0dBm. </li>
+ * <li> index 1 = 0dBm < tx_power < 5dBm. </li>
+ * <li> index 2 = 5dBm < tx_power < 15dBm. </li>
+ * <li> index 3 = 15dBm < tx_power < 20dBm. </li>
+ * <li> index 4 = tx_power > 20dBm. </li>
+ * </ul>
+ */
+ @NonNull
+ public long[] getTxTimeMillis() {
+ return mTxTimeMs;
+ }
- public void setKernelActiveTimeMs(long t) {
- mKernelActiveTimeMs = t;
- return;
- }
+ /**
+ * Returns the energy consumed by cellular chip within {@link #getLoggingDurationMillis()}.
+ *
+ * @return Energy consumed in milli-ampere milli-seconds (mAmS).
+ */
+ public long getMonitoredRailChargeConsumedMaMillis() {
+ return mMonitoredRailChargeConsumedMaMs;
+ }
- public void setNumPacketsTx(long n) {
- mNumPacketsTx = n;
- return;
- }
+ /** @hide **/
+ public void setLoggingDurationMillis(long t) {
+ mLoggingDurationMs = t;
+ return;
+ }
- public void setNumBytesTx(long b) {
- mNumBytesTx = b;
- return;
- }
+ /** @hide **/
+ public void setKernelActiveTimeMillis(long t) {
+ mKernelActiveTimeMs = t;
+ return;
+ }
- public void setNumPacketsRx(long n) {
- mNumPacketsRx = n;
- return;
- }
+ /** @hide **/
+ public void setNumPacketsTx(long n) {
+ mNumPacketsTx = n;
+ return;
+ }
- public void setNumBytesRx(long b) {
- mNumBytesRx = b;
- return;
- }
+ /** @hide **/
+ public void setNumBytesTx(long b) {
+ mNumBytesTx = b;
+ return;
+ }
- public void setSleepTimeMs(long t) {
- mSleepTimeMs = t;
- return;
- }
+ /** @hide **/
+ public void setNumPacketsRx(long n) {
+ mNumPacketsRx = n;
+ return;
+ }
- public void setIdleTimeMs(long t) {
- mIdleTimeMs = t;
- return;
- }
+ /** @hide **/
+ public void setNumBytesRx(long b) {
+ mNumBytesRx = b;
+ return;
+ }
- public void setRxTimeMs(long t) {
- mRxTimeMs = t;
- return;
- }
+ /** @hide **/
+ public void setSleepTimeMillis(long t) {
+ mSleepTimeMs = t;
+ return;
+ }
- public void setEnergyConsumedMaMs(long e) {
- mEnergyConsumedMaMs = e;
- return;
- }
+ /** @hide **/
+ public void setIdleTimeMillis(long t) {
+ mIdleTimeMs = t;
+ return;
+ }
- public void setTimeInRatMs(long[] t) {
- mTimeInRatMs = Arrays.copyOfRange(t, 0,
- Math.min(t.length, BatteryStats.NUM_DATA_CONNECTION_TYPES));
- return;
- }
+ /** @hide **/
+ public void setRxTimeMillis(long t) {
+ mRxTimeMs = t;
+ return;
+ }
- public void setTimeInRxSignalStrengthLevelMs(long[] t) {
- mTimeInRxSignalStrengthLevelMs = Arrays.copyOfRange(t, 0,
- Math.min(t.length, SignalStrength.NUM_SIGNAL_STRENGTH_BINS));
- return;
- }
+ /** @hide **/
+ public void setEnergyConsumedMaMillis(long e) {
+ mEnergyConsumedMaMs = e;
+ return;
+ }
- public void setTxTimeMs(long[] t) {
- mTxTimeMs = Arrays.copyOfRange(t, 0, Math.min(t.length, ModemActivityInfo.TX_POWER_LEVELS));
- return;
- }
+ /** @hide **/
+ public void setTimeInRatMicros(@NonNull long[] t) {
+ mTimeInRatMs = Arrays.copyOfRange(t, 0,
+ Math.min(t.length, BatteryStats.NUM_DATA_CONNECTION_TYPES));
+ return;
+ }
- public void setMonitoredRailChargeConsumedMaMs(long monitoredRailEnergyConsumedMaMs) {
- mMonitoredRailChargeConsumedMaMs = monitoredRailEnergyConsumedMaMs;
- return;
- }
+ /** @hide **/
+ public void setTimeInRxSignalStrengthLevelMicros(@NonNull long[] t) {
+ mTimeInRxSignalStrengthLevelMs = Arrays.copyOfRange(t, 0,
+ Math.min(t.length, SignalStrength.NUM_SIGNAL_STRENGTH_BINS));
+ return;
+ }
- public int describeContents() {
- return 0;
- }
+ /** @hide **/
+ public void setTxTimeMillis(@NonNull long[] t) {
+ mTxTimeMs = Arrays.copyOfRange(t, 0, Math.min(t.length, ModemActivityInfo.TX_POWER_LEVELS));
+ return;
+ }
- private CellularBatteryStats(Parcel in) {
- initialize();
- readFromParcel(in);
- }
+ /** @hide **/
+ public void setMonitoredRailChargeConsumedMaMillis(long monitoredRailEnergyConsumedMaMs) {
+ mMonitoredRailChargeConsumedMaMs = monitoredRailEnergyConsumedMaMs;
+ return;
+ }
- private void initialize() {
- mLoggingDurationMs = 0;
- mKernelActiveTimeMs = 0;
- mNumPacketsTx = 0;
- mNumBytesTx = 0;
- mNumPacketsRx = 0;
- mNumBytesRx = 0;
- mSleepTimeMs = 0;
- mIdleTimeMs = 0;
- mRxTimeMs = 0;
- mEnergyConsumedMaMs = 0;
- mTimeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
- Arrays.fill(mTimeInRatMs, 0);
- mTimeInRxSignalStrengthLevelMs = new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
- Arrays.fill(mTimeInRxSignalStrengthLevelMs, 0);
- mTxTimeMs = new long[ModemActivityInfo.TX_POWER_LEVELS];
- Arrays.fill(mTxTimeMs, 0);
- mMonitoredRailChargeConsumedMaMs = 0;
- return;
- }
-}
\ No newline at end of file
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ private CellularBatteryStats(Parcel in) {
+ readFromParcel(in);
+ }
+}
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 8b8afd5..0401d7f 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -130,8 +130,10 @@
/**
* Namespace for how dex runs. The feature requires a reboot to reach a clean state.
*
+ * @deprecated No longer used
* @hide
*/
+ @Deprecated
@SystemApi
public static final String NAMESPACE_DEX_BOOT = "dex_boot";
@@ -586,9 +588,8 @@
@RequiresPermission(WRITE_DEVICE_CONFIG)
public static boolean setProperty(@NonNull String namespace, @NonNull String name,
@Nullable String value, boolean makeDefault) {
- String compositeName = createCompositeName(namespace, name);
ContentResolver contentResolver = ActivityThread.currentApplication().getContentResolver();
- return Settings.Config.putString(contentResolver, compositeName, value, makeDefault);
+ return Settings.Config.putString(contentResolver, namespace, name, value, makeDefault);
}
/**
@@ -672,12 +673,6 @@
}
}
- private static String createCompositeName(@NonNull String namespace, @NonNull String name) {
- Preconditions.checkNotNull(namespace);
- Preconditions.checkNotNull(name);
- return namespace + "/" + name;
- }
-
private static Uri createNamespaceUri(@NonNull String namespace) {
Preconditions.checkNotNull(namespace);
return CONTENT_URI.buildUpon().appendPath(namespace).build();
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 2143a0d..a80153d 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -1081,7 +1081,8 @@
// signed with platform signature can hold MANAGE_DOCUMENTS, we are going to check for
// MANAGE_DOCUMENTS or associated URI permission here instead
final Uri rootUri = extras.getParcelable(DocumentsContract.EXTRA_URI);
- enforceWritePermissionInner(rootUri, getCallingPackage(), null);
+ enforceWritePermissionInner(rootUri, getCallingPackage(), getCallingFeatureId(),
+ null);
final String rootId = DocumentsContract.getRootId(rootUri);
ejectRoot(rootId);
@@ -1102,7 +1103,8 @@
enforceTree(documentUri);
if (METHOD_IS_CHILD_DOCUMENT.equals(method)) {
- enforceReadPermissionInner(documentUri, getCallingPackage(), null);
+ enforceReadPermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
+ null);
final Uri childUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI);
final String childAuthority = childUri.getAuthority();
@@ -1114,7 +1116,8 @@
&& isChildDocument(documentId, childId));
} else if (METHOD_CREATE_DOCUMENT.equals(method)) {
- enforceWritePermissionInner(documentUri, getCallingPackage(), null);
+ enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
+ null);
final String mimeType = extras.getString(Document.COLUMN_MIME_TYPE);
final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
@@ -1128,7 +1131,8 @@
out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri);
} else if (METHOD_CREATE_WEB_LINK_INTENT.equals(method)) {
- enforceWritePermissionInner(documentUri, getCallingPackage(), null);
+ enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
+ null);
final Bundle options = extras.getBundle(DocumentsContract.EXTRA_OPTIONS);
final IntentSender intentSender = createWebLinkIntent(documentId, options);
@@ -1136,7 +1140,8 @@
out.putParcelable(DocumentsContract.EXTRA_RESULT, intentSender);
} else if (METHOD_RENAME_DOCUMENT.equals(method)) {
- enforceWritePermissionInner(documentUri, getCallingPackage(), null);
+ enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
+ null);
final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
final String newDocumentId = renameDocument(documentId, displayName);
@@ -1160,7 +1165,8 @@
}
} else if (METHOD_DELETE_DOCUMENT.equals(method)) {
- enforceWritePermissionInner(documentUri, getCallingPackage(), null);
+ enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
+ null);
deleteDocument(documentId);
// Document no longer exists, clean up any grants.
@@ -1170,8 +1176,10 @@
final Uri targetUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI);
final String targetId = DocumentsContract.getDocumentId(targetUri);
- enforceReadPermissionInner(documentUri, getCallingPackage(), null);
- enforceWritePermissionInner(targetUri, getCallingPackage(), null);
+ enforceReadPermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
+ null);
+ enforceWritePermissionInner(targetUri, getCallingPackage(), getCallingFeatureId(),
+ null);
final String newDocumentId = copyDocument(documentId, targetId);
@@ -1194,9 +1202,12 @@
final Uri targetUri = extras.getParcelable(DocumentsContract.EXTRA_TARGET_URI);
final String targetId = DocumentsContract.getDocumentId(targetUri);
- enforceWritePermissionInner(documentUri, getCallingPackage(), null);
- enforceReadPermissionInner(parentSourceUri, getCallingPackage(), null);
- enforceWritePermissionInner(targetUri, getCallingPackage(), null);
+ enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
+ null);
+ enforceReadPermissionInner(parentSourceUri, getCallingPackage(), getCallingFeatureId(),
+ null);
+ enforceWritePermissionInner(targetUri, getCallingPackage(), getCallingFeatureId(),
+ null);
final String newDocumentId = moveDocument(documentId, parentSourceId, targetId);
@@ -1217,8 +1228,10 @@
final Uri parentSourceUri = extras.getParcelable(DocumentsContract.EXTRA_PARENT_URI);
final String parentSourceId = DocumentsContract.getDocumentId(parentSourceUri);
- enforceReadPermissionInner(parentSourceUri, getCallingPackage(), null);
- enforceWritePermissionInner(documentUri, getCallingPackage(), null);
+ enforceReadPermissionInner(parentSourceUri, getCallingPackage(), getCallingFeatureId(),
+ null);
+ enforceWritePermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
+ null);
removeDocument(documentId, parentSourceId);
// It's responsibility of the provider to revoke any grants, as the document may be
@@ -1227,7 +1240,8 @@
final boolean isTreeUri = isTreeUri(documentUri);
if (isTreeUri) {
- enforceReadPermissionInner(documentUri, getCallingPackage(), null);
+ enforceReadPermissionInner(documentUri, getCallingPackage(), getCallingFeatureId(),
+ null);
} else {
getContext().enforceCallingPermission(Manifest.permission.MANAGE_DOCUMENTS, null);
}
diff --git a/core/java/android/provider/FontsContract.java b/core/java/android/provider/FontsContract.java
index 8f772d4..fcbda5f 100644
--- a/core/java/android/provider/FontsContract.java
+++ b/core/java/android/provider/FontsContract.java
@@ -334,10 +334,17 @@
return cachedTypeface;
}
- // Unfortunately the typeface is not available at this time, but requesting from the font
- // provider takes too much time. For now, request the font data to ensure it is in the cache
- // next time and return.
synchronized (sLock) {
+ // It is possible that Font is loaded during the thread sleep time
+ // re-check the cache to avoid re-loading the font
+ cachedTypeface = sTypefaceCache.get(id);
+ if (cachedTypeface != null) {
+ return cachedTypeface;
+ }
+
+ // Unfortunately the typeface is not available at this time, but requesting from
+ // the font provider takes too much time. For now, request the font data to ensure
+ // it is in the cache next time and return.
if (sHandler == null) {
sThread = new HandlerThread("fonts", Process.THREAD_PRIORITY_BACKGROUND);
sThread.start();
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index a1333df..aa67d97 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -47,6 +47,7 @@
import android.media.ExifInterface;
import android.media.MediaFile;
import android.media.MediaFormat;
+import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -589,9 +590,7 @@
* @see MediaStore#setIncludeTrashed(Uri)
* @see MediaStore#trash(Context, Uri)
* @see MediaStore#untrash(Context, Uri)
- * @removed
*/
- @Deprecated
public static @NonNull Uri setIncludeTrashed(@NonNull Uri uri) {
return uri.buildUpon().appendQueryParameter(PARAM_INCLUDE_TRASHED, "1").build();
}
@@ -830,9 +829,7 @@
* @see MediaStore#setIncludeTrashed(Uri)
* @see MediaStore#trash(Context, Uri)
* @see MediaStore#untrash(Context, Uri)
- * @removed
*/
- @Deprecated
public static void trash(@NonNull Context context, @NonNull Uri uri) {
trash(context, uri, 48 * DateUtils.HOUR_IN_MILLIS);
}
@@ -850,9 +847,7 @@
* @see MediaStore#setIncludeTrashed(Uri)
* @see MediaStore#trash(Context, Uri)
* @see MediaStore#untrash(Context, Uri)
- * @removed
*/
- @Deprecated
public static void trash(@NonNull Context context, @NonNull Uri uri,
@DurationMillisLong long timeoutMillis) {
if (timeoutMillis < 0) {
@@ -874,9 +869,7 @@
* @see MediaStore#setIncludeTrashed(Uri)
* @see MediaStore#trash(Context, Uri)
* @see MediaStore#untrash(Context, Uri)
- * @removed
*/
- @Deprecated
public static void untrash(@NonNull Context context, @NonNull Uri uri) {
final ContentValues values = new ContentValues();
values.put(MediaColumns.IS_TRASHED, 0);
@@ -907,26 +900,8 @@
public static final String DATA = "_data";
/**
- * Hash of the media item on disk.
- * <p>
- * Contains a 20-byte binary blob which is the SHA-1 hash of the file as
- * persisted on disk. For performance reasons, the hash may not be
- * immediately available, in which case a {@code NULL} value will be
- * returned. If the underlying file is modified, this value will be
- * cleared and recalculated.
- * <p>
- * If you require the hash of a specific item, you can call
- * {@link ContentResolver#canonicalize(Uri)}, which will block until the
- * hash is calculated.
- *
- * @removed
- */
- @Deprecated
- @Column(value = Cursor.FIELD_TYPE_BLOB, readOnly = true)
- public static final String HASH = "_hash";
-
- /**
- * The size of the media item.
+ * Indexed value of {@link File#length()} extracted from this media
+ * item.
*/
@BytesLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
@@ -943,12 +918,6 @@
public static final String DISPLAY_NAME = "_display_name";
/**
- * The title of the media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String TITLE = "title";
-
- /**
* The time the media item was first added.
*/
@CurrentTimeSecondsLong
@@ -956,14 +925,22 @@
public static final String DATE_ADDED = "date_added";
/**
- * The time the media item was last modified.
+ * Indexed value of {@link File#lastModified()} extracted from this
+ * media item.
*/
@CurrentTimeSecondsLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DATE_MODIFIED = "date_modified";
/**
- * The time the media item was taken.
+ * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_DATE} or
+ * {@link ExifInterface#TAG_DATETIME_ORIGINAL} extracted from this media
+ * item.
+ * <p>
+ * Note that images must define both
+ * {@link ExifInterface#TAG_DATETIME_ORIGINAL} and
+ * {@code ExifInterface#TAG_OFFSET_TIME_ORIGINAL} to reliably determine
+ * this value in relation to the epoch.
*/
@CurrentTimeMillisLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
@@ -989,17 +966,6 @@
public static final String MIME_TYPE = "mime_type";
/**
- * The MTP object handle of a newly transfered file.
- * Used to pass the new file's object handle through the media scanner
- * from MTP to the media provider
- * For internal use only by MTP, media scanner and media provider.
- * @hide
- */
- @Deprecated
- // @Column(Cursor.FIELD_TYPE_INTEGER)
- public static final String MEDIA_SCANNER_NEW_OBJECT_ID = "media_scanner_new_object_id";
-
- /**
* Non-zero if the media file is drm-protected
* @hide
*/
@@ -1012,6 +978,10 @@
* Flag indicating if a media item is pending, and still being inserted
* by its owner. While this flag is set, only the owner of the item can
* open the underlying file; requests from other apps will be rejected.
+ * <p>
+ * Pending items are retained either until they are published by setting
+ * the field to {@code 0}, or until they expire as defined by
+ * {@link #DATE_EXPIRES}.
*
* @see MediaStore#setIncludePending(Uri)
*/
@@ -1020,38 +990,54 @@
/**
* Flag indicating if a media item is trashed.
+ * <p>
+ * Trashed items are retained until they expire as defined by
+ * {@link #DATE_EXPIRES}.
*
* @see MediaColumns#IS_TRASHED
* @see MediaStore#setIncludeTrashed(Uri)
* @see MediaStore#trash(Context, Uri)
* @see MediaStore#untrash(Context, Uri)
- * @removed
*/
- @Deprecated
@Column(Cursor.FIELD_TYPE_INTEGER)
public static final String IS_TRASHED = "is_trashed";
/**
* The time the media item should be considered expired. Typically only
- * meaningful in the context of {@link #IS_PENDING}.
+ * meaningful in the context of {@link #IS_PENDING} or
+ * {@link #IS_TRASHED}.
*/
@CurrentTimeSecondsLong
@Column(Cursor.FIELD_TYPE_INTEGER)
public static final String DATE_EXPIRES = "date_expires";
/**
- * The width of the media item, in pixels.
+ * Indexed value of
+ * {@link MediaMetadataRetriever#METADATA_KEY_VIDEO_WIDTH},
+ * {@link MediaMetadataRetriever#METADATA_KEY_IMAGE_WIDTH} or
+ * {@link ExifInterface#TAG_IMAGE_WIDTH} extracted from this media item.
*/
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String WIDTH = "width";
/**
- * The height of the media item, in pixels.
+ * Indexed value of
+ * {@link MediaMetadataRetriever#METADATA_KEY_VIDEO_HEIGHT},
+ * {@link MediaMetadataRetriever#METADATA_KEY_IMAGE_HEIGHT} or
+ * {@link ExifInterface#TAG_IMAGE_LENGTH} extracted from this media
+ * item.
*/
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String HEIGHT = "height";
/**
+ * Calculated value that combines {@link #WIDTH} and {@link #HEIGHT}
+ * into a user-presentable string.
+ */
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ public static final String RESOLUTION = "resolution";
+
+ /**
* Package name that contributed this media. The value may be
* {@code NULL} if ownership cannot be reliably determined.
*/
@@ -1097,28 +1083,6 @@
public static final String RELATIVE_PATH = "relative_path";
/**
- * The primary directory name this media exists under. The value may be
- * {@code NULL} if the media doesn't have a primary directory name.
- *
- * @removed
- * @deprecated Replaced by {@link #RELATIVE_PATH}.
- */
- @Column(Cursor.FIELD_TYPE_STRING)
- @Deprecated
- public static final String PRIMARY_DIRECTORY = "primary_directory";
-
- /**
- * The secondary directory name this media exists under. The value may
- * be {@code NULL} if the media doesn't have a secondary directory name.
- *
- * @removed
- * @deprecated Replaced by {@link #RELATIVE_PATH}.
- */
- @Column(Cursor.FIELD_TYPE_STRING)
- @Deprecated
- public static final String SECONDARY_DIRECTORY = "secondary_directory";
-
- /**
* The primary bucket ID of this media item. This can be useful to
* present the user a first-level clustering of related media items.
* This is a read-only column that is automatically computed.
@@ -1191,18 +1155,171 @@
public static final String ORIGINAL_DOCUMENT_ID = "original_document_id";
/**
- * The duration of the media item.
+ * Indexed value of
+ * {@link MediaMetadataRetriever#METADATA_KEY_VIDEO_ROTATION},
+ * {@link MediaMetadataRetriever#METADATA_KEY_IMAGE_ROTATION}, or
+ * {@link ExifInterface#TAG_ORIENTATION} extracted from this media item.
+ * <p>
+ * For consistency the indexed value is expressed in degrees, such as 0,
+ * 90, 180, or 270.
+ */
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
+ public static final String ORIENTATION = "orientation";
+
+ /**
+ * Flag indicating if the media item has been marked as being a
+ * "favorite" by the user.
+ */
+ @Column(Cursor.FIELD_TYPE_INTEGER)
+ public static final String IS_FAVORITE = "is_favorite";
+
+ // =======================================
+ // ==== MediaMetadataRetriever values ====
+ // =======================================
+
+ /**
+ * Indexed value of
+ * {@link MediaMetadataRetriever#METADATA_KEY_CD_TRACK_NUMBER} extracted
+ * from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ public static final String CD_TRACK_NUMBER = "cd_track_number";
+
+ /**
+ * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_ALBUM}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ public static final String ALBUM = "album";
+
+ /**
+ * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_ARTIST}
+ * or {@link ExifInterface#TAG_ARTIST} extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ public static final String ARTIST = "artist";
+
+ /**
+ * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_AUTHOR}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ public static final String AUTHOR = "author";
+
+ /**
+ * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_COMPOSER}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ public static final String COMPOSER = "composer";
+
+ // METADATA_KEY_DATE is DATE_TAKEN
+
+ /**
+ * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_GENRE}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ public static final String GENRE = "genre";
+
+ /**
+ * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_TITLE}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ public static final String TITLE = "title";
+
+ /**
+ * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_YEAR}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
+ public static final String YEAR = "year";
+
+ /**
+ * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_DURATION}
+ * extracted from this media item.
*/
@DurationMillisLong
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String DURATION = "duration";
/**
- * The orientation for the media item, expressed in degrees. For
- * example, 0, 90, 180, or 270 degrees.
+ * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_NUM_TRACKS}
+ * extracted from this media item.
*/
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
- public static final String ORIENTATION = "orientation";
+ public static final String NUM_TRACKS = "num_tracks";
+
+ /**
+ * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_WRITER}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ public static final String WRITER = "writer";
+
+ // METADATA_KEY_MIMETYPE is MIME_TYPE
+
+ /**
+ * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_ALBUMARTIST}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ public static final String ALBUM_ARTIST = "album_artist";
+
+ /**
+ * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_DISC_NUMBER}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ public static final String DISC_NUMBER = "disc_number";
+
+ /**
+ * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_COMPILATION}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ public static final String COMPILATION = "compilation";
+
+ // HAS_AUDIO is ignored
+ // HAS_VIDEO is ignored
+ // VIDEO_WIDTH is WIDTH
+ // VIDEO_HEIGHT is HEIGHT
+
+ /**
+ * Indexed value of {@link MediaMetadataRetriever#METADATA_KEY_BITRATE}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
+ public static final String BITRATE = "bitrate";
+
+ // TIMED_TEXT_LANGUAGES is ignored
+ // IS_DRM is ignored
+ // LOCATION is LATITUDE and LONGITUDE
+ // VIDEO_ROTATION is ORIENTATION
+
+ /**
+ * Indexed value of
+ * {@link MediaMetadataRetriever#METADATA_KEY_CAPTURE_FRAMERATE}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_FLOAT, readOnly = true)
+ public static final String CAPTURE_FRAMERATE = "capture_framerate";
+
+ // HAS_IMAGE is ignored
+ // IMAGE_COUNT is ignored
+ // IMAGE_PRIMARY is ignored
+ // IMAGE_WIDTH is WIDTH
+ // IMAGE_HEIGHT is HEIGHT
+ // IMAGE_ROTATION is ORIENTATION
+ // VIDEO_FRAME_COUNT is ignored
+ // EXIF_OFFSET is ignored
+ // EXIF_LENGTH is ignored
+ // COLOR_STANDARD is ignored
+ // COLOR_TRANSFER is ignored
+ // COLOR_RANGE is ignored
+ // SAMPLERATE is ignored
+ // BITS_PER_SAMPLE is ignored
}
/**
@@ -1331,10 +1448,7 @@
@Column(Cursor.FIELD_TYPE_STRING)
public static final String MIME_TYPE = "mime_type";
- /**
- * The title of the media item.
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ /** @removed promoted to parent interface */
public static final String TITLE = "title";
/**
@@ -1589,12 +1703,6 @@
*/
public interface ImageColumns extends MediaColumns {
/**
- * The description of the image
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
- public static final String DESCRIPTION = "description";
-
- /**
* The picasa id of the image
*
* @deprecated this value was only relevant for images hosted on
@@ -1656,6 +1764,34 @@
public static final String BUCKET_DISPLAY_NAME = "bucket_display_name";
/** @removed promoted to parent interface */
public static final String GROUP_ID = "group_id";
+
+ /**
+ * Indexed value of {@link ExifInterface#TAG_IMAGE_DESCRIPTION}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ public static final String DESCRIPTION = "description";
+
+ /**
+ * Indexed value of {@link ExifInterface#TAG_EXPOSURE_TIME}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ public static final String EXPOSURE_TIME = "exposure_time";
+
+ /**
+ * Indexed value of {@link ExifInterface#TAG_F_NUMBER}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ public static final String F_NUMBER = "f_number";
+
+ /**
+ * Indexed value of {@link ExifInterface#TAG_ISO_SPEED_RATINGS}
+ * extracted from this media item.
+ */
+ @Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
+ public static final String ISO = "iso";
}
public static final class Media implements ImageColumns {
@@ -1904,6 +2040,10 @@
* generated. Callers are responsible for their own in-memory
* caching of returned values.
*
+ * As of {@link android.os.Build.VERSION_CODES#Q}, this output
+ * of the thumbnail has correct rotation, don't need to rotate
+ * it again.
+ *
* @param imageId the image item to obtain a thumbnail for.
* @param kind optimal thumbnail size desired.
* @return decoded thumbnail, or {@code null} if problem was
@@ -1946,6 +2086,10 @@
* generated. Callers are responsible for their own in-memory
* caching of returned values.
*
+ * As of {@link android.os.Build.VERSION_CODES#Q}, this output
+ * of the thumbnail has correct rotation, don't need to rotate
+ * it again.
+ *
* @param imageId the image item to obtain a thumbnail for.
* @param kind optimal thumbnail size desired.
* @return decoded thumbnail, or {@code null} if problem was
@@ -2000,6 +2144,9 @@
* {@link ContentResolver#openFileDescriptor(Uri, String)} to gain
* access.
*
+ * As of {@link android.os.Build.VERSION_CODES#Q}, this thumbnail
+ * has correct rotation, don't need to rotate it again.
+ *
* @deprecated Apps may not have filesystem permissions to directly
* access this path. Instead of trying to open this path
* directly, apps should use
@@ -2093,10 +2240,7 @@
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String ARTIST_ID = "artist_id";
- /**
- * The artist who created the audio file, if any
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ /** @removed promoted to parent interface */
public static final String ARTIST = "artist";
/**
@@ -2107,14 +2251,6 @@
public static final String ALBUM_ARTIST = "album_artist";
/**
- * Whether the song is part of a compilation
- * @hide
- */
- @Deprecated
- // @Column(Cursor.FIELD_TYPE_STRING)
- public static final String COMPILATION = "compilation";
-
- /**
* A non human readable key calculated from the ARTIST, used for
* searching, sorting and grouping
*
@@ -2131,10 +2267,7 @@
@Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
public static final String ARTIST_KEY = "artist_key";
- /**
- * The composer of the audio file, if any
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ /** @removed promoted to parent interface */
public static final String COMPOSER = "composer";
/**
@@ -2143,10 +2276,7 @@
@Column(value = Cursor.FIELD_TYPE_INTEGER, readOnly = true)
public static final String ALBUM_ID = "album_id";
- /**
- * The album the audio file is from, if any
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ /** @removed promoted to parent interface */
public static final String ALBUM = "album";
/**
@@ -2973,23 +3103,11 @@
public interface VideoColumns extends MediaColumns {
/** @removed promoted to parent interface */
public static final String DURATION = "duration";
-
- /**
- * The artist who created the video file, if any
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ /** @removed promoted to parent interface */
public static final String ARTIST = "artist";
-
- /**
- * The album the video file is from, if any
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ /** @removed promoted to parent interface */
public static final String ALBUM = "album";
-
- /**
- * The resolution of the video file, formatted as "XxY"
- */
- @Column(value = Cursor.FIELD_TYPE_STRING, readOnly = true)
+ /** @removed promoted to parent interface */
public static final String RESOLUTION = "resolution";
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b5580d4..381d492 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -78,6 +78,7 @@
import android.view.Display;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
import com.android.internal.widget.ILockSettings;
import java.io.IOException;
@@ -2306,8 +2307,8 @@
arg.putBoolean(CALL_METHOD_MAKE_DEFAULT_KEY, true);
}
IContentProvider cp = mProviderHolder.getProvider(cr);
- cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(),
- mCallSetCommand, name, arg);
+ cp.call(cr.getPackageName(), cr.getFeatureId(),
+ mProviderHolder.mUri.getAuthority(), mCallSetCommand, name, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't set key " + name + " in " + mUri, e);
return false;
@@ -2380,14 +2381,15 @@
if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) {
final long token = Binder.clearCallingIdentity();
try {
- b = cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(),
- mCallGetCommand, name, args);
+ b = cp.call(cr.getPackageName(), cr.getFeatureId(),
+ mProviderHolder.mUri.getAuthority(), mCallGetCommand, name,
+ args);
} finally {
Binder.restoreCallingIdentity(token);
}
} else {
- b = cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(),
- mCallGetCommand, name, args);
+ b = cp.call(cr.getPackageName(), cr.getFeatureId(),
+ mProviderHolder.mUri.getAuthority(), mCallGetCommand, name, args);
}
if (b != null) {
String value = b.getString(Settings.NameValueTable.VALUE);
@@ -2455,14 +2457,14 @@
if (Settings.isInSystemServer() && Binder.getCallingUid() != Process.myUid()) {
final long token = Binder.clearCallingIdentity();
try {
- c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs,
- null);
+ c = cp.query(cr.getPackageName(), cr.getFeatureId(), mUri,
+ SELECT_VALUE_PROJECTION, queryArgs, null);
} finally {
Binder.restoreCallingIdentity(token);
}
} else {
- c = cp.query(cr.getPackageName(), mUri, SELECT_VALUE_PROJECTION, queryArgs,
- null);
+ c = cp.query(cr.getPackageName(), cr.getFeatureId(), mUri,
+ SELECT_VALUE_PROJECTION, queryArgs, null);
}
if (c == null) {
Log.w(TAG, "Can't get key " + name + " from " + mUri);
@@ -2506,7 +2508,7 @@
boolean prefixCached = false;
int size = mValues.size();
for (int i = 0; i < size; ++i) {
- if (mValues.keyAt(i).startsWith(prefix + "/")) {
+ if (mValues.keyAt(i).startsWith(prefix)) {
prefixCached = true;
break;
}
@@ -2521,7 +2523,7 @@
} else {
for (int i = 0; i < size; ++i) {
String key = mValues.keyAt(i);
- if (key.startsWith(prefix + "/")) {
+ if (key.startsWith(prefix)) {
keyValues.put(key, mValues.get(key));
}
}
@@ -2557,8 +2559,8 @@
}
// Fetch all flags for the namespace at once for caching purposes
- Bundle b = cp.call(cr.getPackageName(), mProviderHolder.mUri.getAuthority(),
- mCallListCommand, null, args);
+ Bundle b = cp.call(cr.getPackageName(), cr.getFeatureId(),
+ mProviderHolder.mUri.getAuthority(), mCallListCommand, null, args);
if (b == null) {
// Invalid response, return an empty map
return keyValues;
@@ -5132,8 +5134,8 @@
}
arg.putInt(CALL_METHOD_RESET_MODE_KEY, mode);
IContentProvider cp = sProviderHolder.getProvider(resolver);
- cp.call(resolver.getPackageName(), sProviderHolder.mUri.getAuthority(),
- CALL_METHOD_RESET_SECURE, null, arg);
+ cp.call(resolver.getPackageName(), resolver.getFeatureId(),
+ sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_SECURE, null, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't reset do defaults for " + CONTENT_URI, e);
}
@@ -8268,6 +8270,12 @@
public static final String AWARE_LOCK_ENABLED = "aware_lock_enabled";
/**
+ * Controls whether tap gesture is enabled.
+ * @hide
+ */
+ public static final String TAP_GESTURE = "tap_gesture";
+
+ /**
* Keys we no longer back up under the current schema, but want to continue to
* process when restoring historical backup datasets.
*
@@ -10646,6 +10654,7 @@
* @hide
* @see com.android.server.AppOpsService.Constants
*/
+ @TestApi
public static final String APP_OPS_CONSTANTS = "app_ops_constants";
/**
@@ -12821,8 +12830,8 @@
}
arg.putInt(CALL_METHOD_RESET_MODE_KEY, mode);
IContentProvider cp = sProviderHolder.getProvider(resolver);
- cp.call(resolver.getPackageName(), sProviderHolder.mUri.getAuthority(),
- CALL_METHOD_RESET_GLOBAL, null, arg);
+ cp.call(resolver.getPackageName(), resolver.getFeatureId(),
+ sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_GLOBAL, null, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't reset do defaults for " + CONTENT_URI, e);
}
@@ -13678,10 +13687,10 @@
}
/**
- * Look up a list of names in the database, based on a common prefix.
+ * Look up a list of names in the database, within the specified namespace.
*
* @param resolver to access the database with
- * @param prefix to apply to all of the names which will be fetched
+ * @param namespace to which the names belong
* @param names to look up in the table
* @return a non null, but possibly empty, map from name to value for any of the names that
* were found during lookup.
@@ -13690,16 +13699,17 @@
*/
@RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
static Map<String, String> getStrings(@NonNull ContentResolver resolver,
- @NonNull String prefix, @NonNull List<String> names) {
- List<String> concatenatedNames = new ArrayList<>(names.size());
+ @NonNull String namespace, @NonNull List<String> names) {
+ List<String> compositeNames = new ArrayList<>(names.size());
for (String name : names) {
- concatenatedNames.add(prefix + "/" + name);
+ compositeNames.add(createCompositeName(namespace, name));
}
+ String prefix = createPrefix(namespace);
ArrayMap<String, String> rawKeyValues = sNameValueCache.getStringsForPrefix(
- resolver, prefix, concatenatedNames);
+ resolver, prefix, compositeNames);
int size = rawKeyValues.size();
- int substringLength = prefix.length() + 1;
+ int substringLength = prefix.length();
ArrayMap<String, String> keyValues = new ArrayMap<>(size);
for (int i = 0; i < size; ++i) {
keyValues.put(rawKeyValues.keyAt(i).substring(substringLength),
@@ -13709,7 +13719,7 @@
}
/**
- * Store a name/value pair into the database.
+ * Store a name/value pair into the database within the specified namespace.
* <p>
* Also the method takes an argument whether to make the value the default for this setting.
* If the system already specified a default value, then the one passed in here will
@@ -13717,6 +13727,7 @@
* </p>
*
* @param resolver to access the database with.
+ * @param namespace to store the name/value pair in.
* @param name to store.
* @param value to associate with the name.
* @param makeDefault whether to make the value the default one.
@@ -13727,10 +13738,10 @@
* @hide
*/
@RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
- static boolean putString(@NonNull ContentResolver resolver, @NonNull String name,
- @Nullable String value, boolean makeDefault) {
- return sNameValueCache.putStringForUser(resolver, name, value, null, makeDefault,
- resolver.getUserId());
+ static boolean putString(@NonNull ContentResolver resolver, @NonNull String namespace,
+ @NonNull String name, @Nullable String value, boolean makeDefault) {
+ return sNameValueCache.putStringForUser(resolver, createCompositeName(namespace, name),
+ value, null, makeDefault, resolver.getUserId());
}
/**
@@ -13741,29 +13752,40 @@
*
* @param resolver Handle to the content resolver.
* @param resetMode The reset mode to use.
- * @param prefix Optionally, to limit which which pairs are reset.
+ * @param namespace Optionally, to limit which which namespace is reset.
*
- * @see #putString(ContentResolver, String, String, boolean)
+ * @see #putString(ContentResolver, String, String, String, boolean)
*
* @hide
*/
@RequiresPermission(Manifest.permission.WRITE_DEVICE_CONFIG)
static void resetToDefaults(@NonNull ContentResolver resolver, @ResetMode int resetMode,
- @Nullable String prefix) {
+ @Nullable String namespace) {
try {
Bundle arg = new Bundle();
arg.putInt(CALL_METHOD_USER_KEY, resolver.getUserId());
arg.putInt(CALL_METHOD_RESET_MODE_KEY, resetMode);
- if (prefix != null) {
- arg.putString(Settings.CALL_METHOD_PREFIX_KEY, prefix);
+ if (namespace != null) {
+ arg.putString(Settings.CALL_METHOD_PREFIX_KEY, createPrefix(namespace));
}
IContentProvider cp = sProviderHolder.getProvider(resolver);
- cp.call(resolver.getPackageName(), sProviderHolder.mUri.getAuthority(),
- CALL_METHOD_RESET_CONFIG, null, arg);
+ cp.call(resolver.getPackageName(), resolver.getFeatureId(),
+ sProviderHolder.mUri.getAuthority(), CALL_METHOD_RESET_CONFIG, null, arg);
} catch (RemoteException e) {
Log.w(TAG, "Can't reset to defaults for " + DeviceConfig.CONTENT_URI, e);
}
}
+
+ private static String createCompositeName(@NonNull String namespace, @NonNull String name) {
+ Preconditions.checkNotNull(namespace);
+ Preconditions.checkNotNull(name);
+ return createPrefix(namespace) + name;
+ }
+
+ private static String createPrefix(@NonNull String namespace) {
+ Preconditions.checkNotNull(namespace);
+ return namespace + "/";
+ }
}
/**
diff --git a/core/java/android/provider/SettingsStringUtil.java b/core/java/android/provider/SettingsStringUtil.java
index a3dc947..9e495dd 100644
--- a/core/java/android/provider/SettingsStringUtil.java
+++ b/core/java/android/provider/SettingsStringUtil.java
@@ -126,7 +126,7 @@
@Override
protected String itemToString(ComponentName item) {
- return item.flattenToString();
+ return item != null ? item.flattenToString() : "null";
}
public static String add(String delimitedElements, ComponentName element) {
diff --git a/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java b/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java
new file mode 100644
index 0000000..de90b94
--- /dev/null
+++ b/core/java/android/service/carrier/CarrierMessagingServiceWrapper.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.carrier;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.List;
+
+/**
+ * Provides basic structure for platform to connect to the carrier messaging service.
+ * <p>
+ * <code>
+ * CarrierMessagingServiceWrapper carrierMessagingServiceWrapper =
+ * new CarrierMessagingServiceWrapperImpl();
+ * if (carrierMessagingServiceWrapper.bindToCarrierMessagingService(context, carrierPackageName)) {
+ * // wait for onServiceReady callback
+ * } else {
+ * // Unable to bind: handle error.
+ * }
+ * </code>
+ * <p> Upon completion {@link #disposeConnection} should be called to unbind the
+ * CarrierMessagingService.
+ * @hide
+ */
+@SystemApi
+public abstract class CarrierMessagingServiceWrapper {
+ // Populated by bindToCarrierMessagingService. bindToCarrierMessagingService must complete
+ // prior to calling disposeConnection so that mCarrierMessagingServiceConnection is initialized.
+ private volatile CarrierMessagingServiceConnection mCarrierMessagingServiceConnection;
+
+ private volatile ICarrierMessagingService mICarrierMessagingService;
+
+ /**
+ * Binds to the carrier messaging service under package {@code carrierPackageName}. This method
+ * should be called exactly once.
+ *
+ * @param context the context
+ * @param carrierPackageName the carrier package name
+ * @return true upon successfully binding to a carrier messaging service, false otherwise
+ * @hide
+ */
+ @SystemApi
+ public boolean bindToCarrierMessagingService(@NonNull Context context,
+ @NonNull String carrierPackageName) {
+ Preconditions.checkState(mCarrierMessagingServiceConnection == null);
+
+ Intent intent = new Intent(CarrierMessagingService.SERVICE_INTERFACE);
+ intent.setPackage(carrierPackageName);
+ mCarrierMessagingServiceConnection = new CarrierMessagingServiceConnection();
+ return context.bindService(intent, mCarrierMessagingServiceConnection,
+ Context.BIND_AUTO_CREATE);
+ }
+
+ /**
+ * Unbinds the carrier messaging service. This method should be called exactly once.
+ *
+ * @param context the context
+ * @hide
+ */
+ @SystemApi
+ public void disposeConnection(@NonNull Context context) {
+ Preconditions.checkNotNull(mCarrierMessagingServiceConnection);
+ context.unbindService(mCarrierMessagingServiceConnection);
+ mCarrierMessagingServiceConnection = null;
+ }
+
+ /**
+ * Implemented by subclasses to use the carrier messaging service once it is ready.
+ * @hide
+ */
+ @SystemApi
+ public abstract void onServiceReady();
+
+ /**
+ * Called when connection with service is established.
+ *
+ * @param carrierMessagingService the carrier messaing service interface
+ */
+ private void onServiceReady(ICarrierMessagingService carrierMessagingService) {
+ mICarrierMessagingService = carrierMessagingService;
+ onServiceReady();
+ }
+
+ /**
+ * Request filtering an incoming SMS message.
+ * The service will call callback.onFilterComplete with the filtering result.
+ *
+ * @param pdu the PDUs of the message
+ * @param format the format of the PDUs, typically "3gpp" or "3gpp2"
+ * @param destPort the destination port of a data SMS. It will be -1 for text SMS
+ * @param subId SMS subscription ID of the SIM
+ * @param callback the callback to notify upon completion
+ * @hide
+ */
+ @SystemApi
+ public void filterSms(@NonNull MessagePdu pdu, @NonNull String format, int destPort,
+ int subId, @NonNull final CarrierMessagingCallbackWrapper callback) {
+ if (mICarrierMessagingService != null) {
+ try {
+ mICarrierMessagingService.filterSms(pdu, format, destPort, subId,
+ new CarrierMessagingCallbackWrapperInternal(callback));
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Request sending a new text SMS from the device.
+ * The service will call {@link ICarrierMessagingCallback#onSendSmsComplete} with the send
+ * status.
+ *
+ * @param text the text to send
+ * @param subId SMS subscription ID of the SIM
+ * @param destAddress phone number of the recipient of the message
+ * @param sendSmsFlag flag for sending SMS
+ * @param callback the callback to notify upon completion
+ * @hide
+ */
+ @SystemApi
+ public void sendTextSms(@NonNull String text, int subId, @NonNull String destAddress,
+ int sendSmsFlag, @NonNull final CarrierMessagingCallbackWrapper callback) {
+ if (mICarrierMessagingService != null) {
+ try {
+ mICarrierMessagingService.sendTextSms(text, subId, destAddress, sendSmsFlag,
+ new CarrierMessagingCallbackWrapperInternal(callback));
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Request sending a new data SMS from the device.
+ * The service will call {@link ICarrierMessagingCallback#onSendSmsComplete} with the send
+ * status.
+ *
+ * @param data the data to send
+ * @param subId SMS subscription ID of the SIM
+ * @param destAddress phone number of the recipient of the message
+ * @param destPort port number of the recipient of the message
+ * @param sendSmsFlag flag for sending SMS
+ * @param callback the callback to notify upon completion
+ * @hide
+ */
+ @SystemApi
+ public void sendDataSms(@NonNull byte[] data, int subId, @NonNull String destAddress,
+ int destPort, int sendSmsFlag,
+ @NonNull final CarrierMessagingCallbackWrapper callback) {
+ if (mICarrierMessagingService != null) {
+ try {
+ mICarrierMessagingService.sendDataSms(data, subId, destAddress, destPort,
+ sendSmsFlag, new CarrierMessagingCallbackWrapperInternal(callback));
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Request sending a new multi-part text SMS from the device.
+ * The service will call {@link ICarrierMessagingCallback#onSendMultipartSmsComplete}
+ * with the send status.
+ *
+ * @param parts the parts of the multi-part text SMS to send
+ * @param subId SMS subscription ID of the SIM
+ * @param destAddress phone number of the recipient of the message
+ * @param sendSmsFlag flag for sending SMS
+ * @param callback the callback to notify upon completion
+ * @hide
+ */
+ @SystemApi
+ public void sendMultipartTextSms(@NonNull List<String> parts, int subId,
+ @NonNull String destAddress, int sendSmsFlag,
+ @NonNull final CarrierMessagingCallbackWrapper callback) {
+ if (mICarrierMessagingService != null) {
+ try {
+ mICarrierMessagingService.sendMultipartTextSms(parts, subId, destAddress,
+ sendSmsFlag, new CarrierMessagingCallbackWrapperInternal(callback));
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Request sending a new MMS PDU from the device.
+ * The service will call {@link ICarrierMessagingCallback#onSendMmsComplete} with the send
+ * status.
+ *
+ * @param pduUri the content provider URI of the PDU to send
+ * @param subId SMS subscription ID of the SIM
+ * @param location the optional URI to send this MMS PDU. If this is {code null},
+ * the PDU should be sent to the default MMSC URL.
+ * @param callback the callback to notify upon completion
+ * @hide
+ */
+ @SystemApi
+ public void sendMms(@NonNull Uri pduUri, int subId, @NonNull Uri location,
+ @NonNull final CarrierMessagingCallbackWrapper callback) {
+ if (mICarrierMessagingService != null) {
+ try {
+ mICarrierMessagingService.sendMms(pduUri, subId, location,
+ new CarrierMessagingCallbackWrapperInternal(callback));
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Request downloading a new MMS.
+ * The service will call {@link ICarrierMessagingCallback#onDownloadMmsComplete} with the
+ * download status.
+ *
+ * @param pduUri the content provider URI of the PDU to be downloaded.
+ * @param subId SMS subscription ID of the SIM
+ * @param location the URI of the message to be downloaded.
+ * @param callback the callback to notify upon completion
+ * @hide
+ */
+ @SystemApi
+ public void downloadMms(@NonNull Uri pduUri, int subId, @NonNull Uri location,
+ @NonNull final CarrierMessagingCallbackWrapper callback) {
+ if (mICarrierMessagingService != null) {
+ try {
+ mICarrierMessagingService.downloadMms(pduUri, subId, location,
+ new CarrierMessagingCallbackWrapperInternal(callback));
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * A basic {@link ServiceConnection}.
+ */
+ private final class CarrierMessagingServiceConnection implements ServiceConnection {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ onServiceReady(ICarrierMessagingService.Stub.asInterface(service));
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ }
+ }
+
+ /**
+ * Callback wrapper used for response to requests exposed by
+ * {@link CarrierMessagingServiceWrapper}.
+ * @hide
+ */
+ @SystemApi
+ public abstract static class CarrierMessagingCallbackWrapper {
+
+ /**
+ * Response callback for {@link CarrierMessagingServiceWrapper#filterSms}.
+ * @param result a bitmask integer to indicate how the incoming text SMS should be handled
+ * by the platform. Bits set can be
+ * {@link CarrierMessagingService#RECEIVE_OPTIONS_DROP} and
+ * {@link CarrierMessagingService#
+ * RECEIVE_OPTIONS_SKIP_NOTIFY_WHEN_CREDENTIAL_PROTECTED_STORAGE_UNAVAILABLE}.
+ * {@see CarrierMessagingService#onReceiveTextSms}.
+ * @hide
+ */
+ @SystemApi
+ public void onFilterComplete(int result) {
+
+ }
+
+ /**
+ * Response callback for {@link CarrierMessagingServiceWrapper#sendTextSms} and
+ * {@link CarrierMessagingServiceWrapper#sendDataSms}.
+ * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK},
+ * {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK},
+ * and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
+ * @param messageRef message reference of the just-sent message. This field is applicable
+ * only if result is {@link CarrierMessagingService#SEND_STATUS_OK}.
+ * @hide
+ */
+ @SystemApi
+ public void onSendSmsComplete(int result, int messageRef) {
+
+ }
+
+ /**
+ * Response callback for {@link CarrierMessagingServiceWrapper#sendMultipartTextSms}.
+ * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK},
+ * {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK},
+ * and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
+ * @param messageRefs an array of message references, one for each part of the
+ * multipart SMS. This field is applicable only if result is
+ * {@link CarrierMessagingService#SEND_STATUS_OK}.
+ * @hide
+ */
+ @SystemApi
+ public void onSendMultipartSmsComplete(int result, @Nullable int[] messageRefs) {
+
+ }
+
+ /**
+ * Response callback for {@link CarrierMessagingServiceWrapper#sendMms}.
+ * @param result send status, one of {@link CarrierMessagingService#SEND_STATUS_OK},
+ * {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK},
+ * and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
+ * @param sendConfPdu a possibly {code null} SendConf PDU, which confirms that the message
+ * was sent. sendConfPdu is ignored if the {@code result} is not
+ * {@link CarrierMessagingService#SEND_STATUS_OK}.
+ * @hide
+ */
+ @SystemApi
+ public void onSendMmsComplete(int result, @Nullable byte[] sendConfPdu) {
+
+ }
+
+ /**
+ * Response callback for {@link CarrierMessagingServiceWrapper#downloadMms}.
+ * @param result download status, one of {@link CarrierMessagingService#SEND_STATUS_OK},
+ * {@link CarrierMessagingService#SEND_STATUS_RETRY_ON_CARRIER_NETWORK},
+ * and {@link CarrierMessagingService#SEND_STATUS_ERROR}.
+ * @hide
+ */
+ @SystemApi
+ public void onDownloadMmsComplete(int result) {
+
+ }
+ }
+
+ private final class CarrierMessagingCallbackWrapperInternal
+ extends ICarrierMessagingCallback.Stub {
+ CarrierMessagingCallbackWrapper mCarrierMessagingCallbackWrapper;
+
+ CarrierMessagingCallbackWrapperInternal(CarrierMessagingCallbackWrapper callback) {
+ mCarrierMessagingCallbackWrapper = callback;
+ }
+
+ @Override
+ public void onFilterComplete(int result) throws RemoteException {
+ mCarrierMessagingCallbackWrapper.onFilterComplete(result);
+ }
+
+ @Override
+ public void onSendSmsComplete(int result, int messageRef) throws RemoteException {
+ mCarrierMessagingCallbackWrapper.onSendSmsComplete(result, messageRef);
+ }
+
+ @Override
+ public void onSendMultipartSmsComplete(int result, int[] messageRefs)
+ throws RemoteException {
+ mCarrierMessagingCallbackWrapper.onSendMultipartSmsComplete(result, messageRefs);
+ }
+
+ @Override
+ public void onSendMmsComplete(int result, byte[] sendConfPdu) throws RemoteException {
+ mCarrierMessagingCallbackWrapper.onSendMmsComplete(result, sendConfPdu);
+ }
+
+ @Override
+ public void onDownloadMmsComplete(int result) throws RemoteException {
+ mCarrierMessagingCallbackWrapper.onDownloadMmsComplete(result);
+ }
+ }
+}
diff --git a/core/java/android/speech/IRecognitionService.aidl b/core/java/android/speech/IRecognitionService.aidl
index be6ef6d2..f91e122 100644
--- a/core/java/android/speech/IRecognitionService.aidl
+++ b/core/java/android/speech/IRecognitionService.aidl
@@ -39,8 +39,11 @@
* this intent can contain extra parameters to manipulate the behavior of the recognition
* client. For more information see {@link RecognizerIntent}.
* @param listener to receive callbacks, note that this must be non-null
+ * @param packageName the package name calling this API
+ * @param featureId The feature in the package
*/
- void startListening(in Intent recognizerIntent, in IRecognitionListener listener);
+ void startListening(in Intent recognizerIntent, in IRecognitionListener listener,
+ String packageName, String featureId);
/**
* Stops listening for speech. Speech captured so far will be recognized as
@@ -48,13 +51,17 @@
* is called during the speech capturing.
*
* @param listener to receive callbacks, note that this must be non-null
+ * @param packageName the package name calling this API
+ * @param featureId The feature in the package
*/
- void stopListening(in IRecognitionListener listener);
+ void stopListening(in IRecognitionListener listener, String packageName, String featureId);
/**
* Cancels the speech recognition.
*
* @param listener to receive callbacks, note that this must be non-null
+ * @param packageName the package name calling this API
+ * @param featureId The feature in the package
*/
- void cancel(in IRecognitionListener listener);
+ void cancel(in IRecognitionListener listener, String packageName, String featureId);
}
diff --git a/core/java/android/speech/RecognitionService.java b/core/java/android/speech/RecognitionService.java
index dfc5c82..4b42209 100644
--- a/core/java/android/speech/RecognitionService.java
+++ b/core/java/android/speech/RecognitionService.java
@@ -16,6 +16,8 @@
package android.speech;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.Service;
@@ -29,6 +31,8 @@
import android.os.RemoteException;
import android.util.Log;
+import com.android.internal.util.Preconditions;
+
import java.lang.ref.WeakReference;
/**
@@ -171,13 +175,17 @@
*
* @param listener to send the error message to in case of error
* @param forDataDelivery If the permission check is for delivering the sensitive data.
+ * @param packageName the package name of the caller
+ * @param featureId The feature in the package
* @return {@code true} if the caller has enough permissions, {@code false} otherwise
*/
- private boolean checkPermissions(IRecognitionListener listener, boolean forDataDelivery) {
+ private boolean checkPermissions(IRecognitionListener listener, boolean forDataDelivery,
+ @NonNull String packageName, @Nullable String featureId) {
if (DBG) Log.d(TAG, "checkPermissions");
if (forDataDelivery) {
- if (PermissionChecker.checkCallingOrSelfPermissionForDataDelivery(this,
- android.Manifest.permission.RECORD_AUDIO, null /*message*/)
+ if (PermissionChecker.checkCallingPermissionForDataDelivery(this,
+ android.Manifest.permission.RECORD_AUDIO, packageName, featureId,
+ null /*message*/)
== PermissionChecker.PERMISSION_GRANTED) {
return true;
}
@@ -349,10 +357,14 @@
}
@Override
- public void startListening(Intent recognizerIntent, IRecognitionListener listener) {
+ public void startListening(Intent recognizerIntent, IRecognitionListener listener,
+ String packageName, String featureId) {
+ Preconditions.checkNotNull(packageName);
+
if (DBG) Log.d(TAG, "startListening called by:" + listener.asBinder());
final RecognitionService service = mServiceRef.get();
- if (service != null && service.checkPermissions(listener, true /*forDataDelivery*/)) {
+ if (service != null && service.checkPermissions(listener, true /*forDataDelivery*/,
+ packageName, featureId)) {
service.mHandler.sendMessage(Message.obtain(service.mHandler,
MSG_START_LISTENING, service.new StartListeningArgs(
recognizerIntent, listener, Binder.getCallingUid())));
@@ -360,20 +372,28 @@
}
@Override
- public void stopListening(IRecognitionListener listener) {
+ public void stopListening(IRecognitionListener listener, String packageName,
+ String featureId) {
+ Preconditions.checkNotNull(packageName);
+
if (DBG) Log.d(TAG, "stopListening called by:" + listener.asBinder());
final RecognitionService service = mServiceRef.get();
- if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/)) {
+ if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/,
+ packageName, featureId)) {
service.mHandler.sendMessage(Message.obtain(service.mHandler,
MSG_STOP_LISTENING, listener));
}
}
@Override
- public void cancel(IRecognitionListener listener) {
+ public void cancel(IRecognitionListener listener, String packageName,
+ String featureId) {
+ Preconditions.checkNotNull(packageName);
+
if (DBG) Log.d(TAG, "cancel called by:" + listener.asBinder());
final RecognitionService service = mServiceRef.get();
- if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/)) {
+ if (service != null && service.checkPermissions(listener, false /*forDataDelivery*/,
+ packageName, featureId)) {
service.mHandler.sendMessage(Message.obtain(service.mHandler,
MSG_CANCEL, listener));
}
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index 88e2ede..e93ba16 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -341,7 +341,8 @@
return;
}
try {
- mService.startListening(recognizerIntent, mListener);
+ mService.startListening(recognizerIntent, mListener, mContext.getOpPackageName(),
+ mContext.getFeatureId());
if (DBG) Log.d(TAG, "service start listening command succeded");
} catch (final RemoteException e) {
Log.e(TAG, "startListening() failed", e);
@@ -355,7 +356,8 @@
return;
}
try {
- mService.stopListening(mListener);
+ mService.stopListening(mListener, mContext.getOpPackageName(),
+ mContext.getFeatureId());
if (DBG) Log.d(TAG, "service stop listening command succeded");
} catch (final RemoteException e) {
Log.e(TAG, "stopListening() failed", e);
@@ -369,7 +371,7 @@
return;
}
try {
- mService.cancel(mListener);
+ mService.cancel(mListener, mContext.getOpPackageName(), mContext.getFeatureId());
if (DBG) Log.d(TAG, "service cancel command succeded");
} catch (final RemoteException e) {
Log.e(TAG, "cancel() failed", e);
@@ -398,7 +400,7 @@
public void destroy() {
if (mService != null) {
try {
- mService.cancel(mListener);
+ mService.cancel(mListener, mContext.getOpPackageName(), mContext.getFeatureId());
} catch (final RemoteException e) {
// Not important
}
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index b1fd4e5..af1a51f 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -47,8 +47,6 @@
static {
DEFAULT_FLAGS = new HashMap<>();
DEFAULT_FLAGS.put("settings_audio_switcher", "true");
- DEFAULT_FLAGS.put("settings_mobile_network_v2", "true");
- DEFAULT_FLAGS.put("settings_network_and_internet_v2", "true");
DEFAULT_FLAGS.put("settings_systemui_theme", "true");
DEFAULT_FLAGS.put(DYNAMIC_SYSTEM, "false");
DEFAULT_FLAGS.put(SEAMLESS_TRANSFER, "false");
diff --git a/core/java/android/util/StatsEvent.java b/core/java/android/util/StatsEvent.java
index 91a5ec0..a21f9e0 100644
--- a/core/java/android/util/StatsEvent.java
+++ b/core/java/android/util/StatsEvent.java
@@ -20,312 +20,615 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.SystemClock;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
/**
* StatsEvent builds and stores the buffer sent over the statsd socket.
* This class defines and encapsulates the socket protocol.
+ *
+ * <p>Usage:</p>
+ * <pre>
+ * StatsEvent statsEvent = StatsEvent.newBuilder()
+ * .setAtomId(atomId)
+ * .writeBoolean(false)
+ * .writeString("annotated String field")
+ * .addBooleanAnnotation(annotationId, true)
+ * .build();
+ *
+ * StatsLog.write(statsEvent);
+ * </pre>
* @hide
**/
-public final class StatsEvent implements AutoCloseable {
- private static final int POS_NUM_ELEMENTS = 1;
- private static final int POS_TIMESTAMP = POS_NUM_ELEMENTS + 1;
-
+public final class StatsEvent {
private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;
- // Max payload size is 4 KB less 4 bytes which are reserved for statsEventTag.
+ // Max payload size is 4 bytes less as 4 bytes are reserved for statsEventTag.
// See android_util_StatsLog.cpp.
- private static final int MAX_EVENT_PAYLOAD = LOGGER_ENTRY_MAX_PAYLOAD - 4;
+ private static final int MAX_PAYLOAD_SIZE = LOGGER_ENTRY_MAX_PAYLOAD - 4;
- private static final byte INT_TYPE = 0;
- private static final byte LONG_TYPE = 1;
- private static final byte STRING_TYPE = 2;
- private static final byte LIST_TYPE = 3;
- private static final byte FLOAT_TYPE = 4;
+ private final int mAtomId;
+ private final Buffer mBuffer;
+ private final int mNumBytes;
- private static final int INT_TYPE_SIZE = 5;
- private static final int FLOAT_TYPE_SIZE = 5;
- private static final int LONG_TYPE_SIZE = 9;
-
- private static final int STRING_TYPE_OVERHEAD = 5;
- private static final int LIST_TYPE_OVERHEAD = 2;
-
- public static final int SUCCESS = 0;
- public static final int ERROR_BUFFER_LIMIT_EXCEEDED = -1;
- public static final int ERROR_NO_TIMESTAMP = -2;
- public static final int ERROR_TIMESTAMP_ALREADY_WRITTEN = -3;
- public static final int ERROR_NO_ATOM_ID = -4;
- public static final int ERROR_ATOM_ID_ALREADY_WRITTEN = -5;
- public static final int ERROR_UID_TAG_COUNT_MISMATCH = -6;
-
- private static Object sLock = new Object();
-
- @GuardedBy("sLock")
- private static StatsEvent sPool;
-
- private final byte[] mBuffer = new byte[MAX_EVENT_PAYLOAD];
- private int mPos;
- private int mNumElements;
- private int mAtomId;
-
- private StatsEvent() {
- // Write LIST_TYPE to buffer
- mBuffer[0] = LIST_TYPE;
- reset();
- }
-
- private void reset() {
- // Reset state.
- mPos = POS_TIMESTAMP;
- mNumElements = 0;
- mAtomId = 0;
+ private StatsEvent(final int atomId, @NonNull final Buffer buffer, final int numBytes) {
+ mAtomId = atomId;
+ mBuffer = buffer;
+ mNumBytes = numBytes;
}
/**
- * Returns a StatsEvent object from the pool.
+ * Returns a new StatsEvent.Builder for building StatsEvent object.
**/
@NonNull
- public static StatsEvent obtain() {
- final StatsEvent statsEvent;
- synchronized (sLock) {
- statsEvent = null == sPool ? new StatsEvent() : sPool;
- sPool = null;
- }
- statsEvent.reset();
- return statsEvent;
+ public StatsEvent.Builder newBuilder() {
+ return new StatsEvent.Builder(Buffer.obtain());
}
- @Override
- public void close() {
- synchronized (sLock) {
- if (null == sPool) {
- sPool = this;
- }
- }
- }
-
- /**
- * Writes the event timestamp to the buffer.
- **/
- public int writeTimestampNs(final long timestampNs) {
- if (hasTimestamp()) {
- return ERROR_TIMESTAMP_ALREADY_WRITTEN;
- }
- return writeLong(timestampNs);
- }
-
- private boolean hasTimestamp() {
- return mPos > POS_TIMESTAMP;
- }
-
- private boolean hasAtomId() {
- return mAtomId != 0;
- }
-
- /**
- * Writes the atom id to the buffer.
- **/
- public int writeAtomId(final int atomId) {
- if (!hasTimestamp()) {
- return ERROR_NO_TIMESTAMP;
- } else if (hasAtomId()) {
- return ERROR_ATOM_ID_ALREADY_WRITTEN;
- }
-
- final int writeResult = writeInt(atomId);
- if (SUCCESS == writeResult) {
- mAtomId = atomId;
- }
- return writeResult;
- }
-
- /**
- * Appends the given int to the StatsEvent buffer.
- **/
- public int writeInt(final int value) {
- if (!hasTimestamp()) {
- return ERROR_NO_TIMESTAMP;
- } else if (!hasAtomId()) {
- return ERROR_NO_ATOM_ID;
- } else if (mPos + INT_TYPE_SIZE > MAX_EVENT_PAYLOAD) {
- return ERROR_BUFFER_LIMIT_EXCEEDED;
- }
-
- mBuffer[mPos] = INT_TYPE;
- copyInt(mBuffer, mPos + 1, value);
- mPos += INT_TYPE_SIZE;
- mNumElements++;
- return SUCCESS;
- }
-
- /**
- * Appends the given long to the StatsEvent buffer.
- **/
- public int writeLong(final long value) {
- if (!hasTimestamp()) {
- return ERROR_NO_TIMESTAMP;
- } else if (!hasAtomId()) {
- return ERROR_NO_ATOM_ID;
- } else if (mPos + LONG_TYPE_SIZE > MAX_EVENT_PAYLOAD) {
- return ERROR_BUFFER_LIMIT_EXCEEDED;
- }
-
- mBuffer[mPos] = LONG_TYPE;
- copyLong(mBuffer, mPos + 1, value);
- mPos += LONG_TYPE_SIZE;
- mNumElements++;
- return SUCCESS;
- }
-
- /**
- * Appends the given float to the StatsEvent buffer.
- **/
- public int writeFloat(final float value) {
- if (!hasTimestamp()) {
- return ERROR_NO_TIMESTAMP;
- } else if (!hasAtomId()) {
- return ERROR_NO_ATOM_ID;
- } else if (mPos + FLOAT_TYPE_SIZE > MAX_EVENT_PAYLOAD) {
- return ERROR_BUFFER_LIMIT_EXCEEDED;
- }
-
- mBuffer[mPos] = FLOAT_TYPE;
- copyInt(mBuffer, mPos + 1, Float.floatToIntBits(value));
- mPos += FLOAT_TYPE_SIZE;
- mNumElements++;
- return SUCCESS;
- }
-
- /**
- * Appends the given boolean to the StatsEvent buffer.
- **/
- public int writeBoolean(final boolean value) {
- return writeInt(value ? 1 : 0);
- }
-
- /**
- * Appends the given byte array to the StatsEvent buffer.
- **/
- public int writeByteArray(@NonNull final byte[] value) {
- if (!hasTimestamp()) {
- return ERROR_NO_TIMESTAMP;
- } else if (!hasAtomId()) {
- return ERROR_NO_ATOM_ID;
- } else if (mPos + STRING_TYPE_OVERHEAD + value.length > MAX_EVENT_PAYLOAD) {
- return ERROR_BUFFER_LIMIT_EXCEEDED;
- }
-
- mBuffer[mPos] = STRING_TYPE;
- copyInt(mBuffer, mPos + 1, value.length);
- System.arraycopy(value, 0, mBuffer, mPos + STRING_TYPE_OVERHEAD, value.length);
- mPos += STRING_TYPE_OVERHEAD + value.length;
- mNumElements++;
- return SUCCESS;
- }
-
- /**
- * Appends the given String to the StatsEvent buffer.
- **/
- public int writeString(@NonNull final String value) {
- final byte[] valueBytes = stringToBytes(value);
- return writeByteArray(valueBytes);
- }
-
- /**
- * Appends the AttributionNode specified as array of uids and array of tags.
- **/
- public int writeAttributionNode(@NonNull final int[] uids, @NonNull final String[] tags) {
- if (!hasTimestamp()) {
- return ERROR_NO_TIMESTAMP;
- } else if (!hasAtomId()) {
- return ERROR_NO_ATOM_ID;
- } else if (mPos + LIST_TYPE_OVERHEAD > MAX_EVENT_PAYLOAD) {
- return ERROR_BUFFER_LIMIT_EXCEEDED;
- }
-
- final int numTags = tags.length;
- final int numUids = uids.length;
- if (numTags != numUids) {
- return ERROR_UID_TAG_COUNT_MISMATCH;
- }
-
- int pos = mPos;
- mBuffer[pos] = LIST_TYPE;
- mBuffer[pos + 1] = (byte) numTags;
- pos += LIST_TYPE_OVERHEAD;
- for (int i = 0; i < numTags; i++) {
- final byte[] tagBytes = stringToBytes(tags[i]);
-
- if (pos + LIST_TYPE_OVERHEAD + INT_TYPE_SIZE
- + STRING_TYPE_OVERHEAD + tagBytes.length > MAX_EVENT_PAYLOAD) {
- return ERROR_BUFFER_LIMIT_EXCEEDED;
- }
-
- mBuffer[pos] = LIST_TYPE;
- mBuffer[pos + 1] = 2;
- pos += LIST_TYPE_OVERHEAD;
- mBuffer[pos] = INT_TYPE;
- copyInt(mBuffer, pos + 1, uids[i]);
- pos += INT_TYPE_SIZE;
- mBuffer[pos] = STRING_TYPE;
- copyInt(mBuffer, pos + 1, tagBytes.length);
- System.arraycopy(tagBytes, 0, mBuffer, pos + STRING_TYPE_OVERHEAD, tagBytes.length);
- pos += STRING_TYPE_OVERHEAD + tagBytes.length;
- }
- mPos = pos;
- mNumElements++;
- return SUCCESS;
- }
-
- /**
- * Returns the byte array containing data in the statsd socket format.
- * @hide
- **/
- @NonNull
- public byte[] getBuffer() {
- // Encode number of elements in the buffer.
- mBuffer[POS_NUM_ELEMENTS] = (byte) mNumElements;
- return mBuffer;
- }
-
- /**
- * Returns number of bytes used by the buffer.
- * @hide
- **/
- public int size() {
- return mPos;
- }
-
- /**
- * Getter for atom id.
- * @hide
- **/
- public int getAtomId() {
+ int getAtomId() {
return mAtomId;
}
@NonNull
- private static byte[] stringToBytes(@Nullable final String value) {
- return (null == value ? "" : value).getBytes(UTF_8);
+ byte[] getBytes() {
+ return mBuffer.getBytes();
}
- // Helper methods for copying primitives
- private static void copyInt(@NonNull byte[] buff, int pos, int value) {
- buff[pos] = (byte) (value);
- buff[pos + 1] = (byte) (value >> 8);
- buff[pos + 2] = (byte) (value >> 16);
- buff[pos + 3] = (byte) (value >> 24);
+ int getNumBytes() {
+ return mNumBytes;
}
- private static void copyLong(@NonNull byte[] buff, int pos, long value) {
- buff[pos] = (byte) (value);
- buff[pos + 1] = (byte) (value >> 8);
- buff[pos + 2] = (byte) (value >> 16);
- buff[pos + 3] = (byte) (value >> 24);
- buff[pos + 4] = (byte) (value >> 32);
- buff[pos + 5] = (byte) (value >> 40);
- buff[pos + 6] = (byte) (value >> 48);
- buff[pos + 7] = (byte) (value >> 56);
+ void release() {
+ mBuffer.release();
+ }
+
+ /**
+ * Builder for constructing a StatsEvent object.
+ *
+ * <p>This class defines and encapsulates the socket encoding for the buffer.
+ * The write methods must be called in the same order as the order of fields in the
+ * atom definition.</p>
+ *
+ * <p>setAtomId() can be called anytime before build().</p>
+ *
+ * <p>Example:</p>
+ * <pre>
+ * // Atom definition.
+ * message MyAtom {
+ * optional int32 field1 = 1;
+ * optional int64 field2 = 2;
+ * optional string field3 = 3 [(annotation1) = true];
+ * }
+ *
+ * // StatsEvent construction.
+ * StatsEvent.newBuilder()
+ * StatsEvent statsEvent = StatsEvent.newBuilder()
+ * .setAtomId(atomId)
+ * .writeInt(3) // field1
+ * .writeLong(8L) // field2
+ * .writeString("foo") // field 3
+ * .addBooleanAnnotation(annotation1Id, true)
+ * .build();
+ * </pre>
+ * @hide
+ **/
+ public static final class Builder {
+ // Type Ids.
+ private static final byte TYPE_INT = 0x00;
+ private static final byte TYPE_LONG = 0x01;
+ private static final byte TYPE_STRING = 0x02;
+ private static final byte TYPE_LIST = 0x03;
+ private static final byte TYPE_FLOAT = 0x04;
+ private static final byte TYPE_BOOLEAN = 0x05;
+ private static final byte TYPE_BYTE_ARRAY = 0x06;
+ private static final byte TYPE_OBJECT = 0x07;
+ private static final byte TYPE_KEY_VALUE_PAIRS = 0x08;
+ private static final byte TYPE_ATTRIBUTION_CHAIN = 0x09;
+ private static final byte TYPE_ERRORS = 0x0F;
+
+ // Error flags.
+ private static final int ERROR_NO_TIMESTAMP = 0x1;
+ private static final int ERROR_NO_ATOM_ID = 0x2;
+ private static final int ERROR_OVERFLOW = 0x4;
+ private static final int ERROR_ATTRIBUTION_CHAIN_TOO_LONG = 0x8;
+ private static final int ERROR_TOO_MANY_KEY_VALUE_PAIRS = 0x10;
+ private static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x20;
+ private static final int ERROR_INVALID_ANNOTATION_ID = 0x40;
+ private static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x80;
+ private static final int ERROR_TOO_MANY_ANNOTATIONS = 0x100;
+ private static final int ERROR_TOO_MANY_FIELDS = 0x200;
+ private static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x400;
+
+ // Size limits.
+ private static final int MAX_ANNOTATION_COUNT = 15;
+ private static final int MAX_ATTRIBUTION_NODES = 127;
+ private static final int MAX_NUM_ELEMENTS = 127;
+ private static final int MAX_KEY_VALUE_PAIRS = 127;
+
+ // Fixed positions.
+ private static final int POS_NUM_ELEMENTS = 1;
+ private static final int POS_TIMESTAMP_NS = POS_NUM_ELEMENTS + Byte.BYTES;
+ private static final int POS_ATOM_ID = POS_TIMESTAMP_NS + Byte.BYTES + Long.BYTES;
+
+ private final Buffer mBuffer;
+ private long mTimestampNs;
+ private int mAtomId;
+ private byte mCurrentAnnotationCount;
+ private int mPos;
+ private int mPosLastField;
+ private byte mLastType;
+ private int mNumElements;
+ private int mErrorMask;
+
+ private Builder(final Buffer buffer) {
+ mBuffer = buffer;
+ mCurrentAnnotationCount = 0;
+ mAtomId = 0;
+ mTimestampNs = SystemClock.elapsedRealtimeNanos();
+ mNumElements = 0;
+
+ // Set mPos to 0 for writing TYPE_OBJECT at 0th position.
+ mPos = 0;
+ writeTypeId(TYPE_OBJECT);
+
+ // Set mPos to after atom id's location in the buffer.
+ // First 2 elements in the buffer are event timestamp followed by the atom id.
+ mPos = POS_ATOM_ID + Byte.BYTES + Integer.BYTES;
+ mPosLastField = 0;
+ mLastType = 0;
+ }
+
+ /**
+ * Sets the atom id for this StatsEvent.
+ **/
+ @NonNull
+ public Builder setAtomId(final int atomId) {
+ mAtomId = atomId;
+ return this;
+ }
+
+ /**
+ * Sets the timestamp in nanos for this StatsEvent.
+ **/
+ @VisibleForTesting
+ @NonNull
+ public Builder setTimestampNs(final long timestampNs) {
+ mTimestampNs = timestampNs;
+ return this;
+ }
+
+ /**
+ * Write a boolean field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeBoolean(final boolean value) {
+ // Write boolean typeId byte followed by boolean byte representation.
+ writeTypeId(TYPE_BOOLEAN);
+ mPos += mBuffer.putBoolean(mPos, value);
+ mNumElements++;
+ return this;
+ }
+
+ /**
+ * Write an integer field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeInt(final int value) {
+ // Write integer typeId byte followed by 4-byte representation of value.
+ writeTypeId(TYPE_INT);
+ mPos += mBuffer.putInt(mPos, value);
+ mNumElements++;
+ return this;
+ }
+
+ /**
+ * Write a long field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeLong(final long value) {
+ // Write long typeId byte followed by 8-byte representation of value.
+ writeTypeId(TYPE_LONG);
+ mPos += mBuffer.putLong(mPos, value);
+ mNumElements++;
+ return this;
+ }
+
+ /**
+ * Write a float field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeFloat(final float value) {
+ // Write float typeId byte followed by 4-byte representation of value.
+ writeTypeId(TYPE_FLOAT);
+ mPos += mBuffer.putFloat(mPos, value);
+ mNumElements++;
+ return this;
+ }
+
+ /**
+ * Write a String field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeString(@NonNull final String value) {
+ // Write String typeId byte, followed by 4-byte representation of number of bytes
+ // in the UTF-8 encoding, followed by the actual UTF-8 byte encoding of value.
+ final byte[] valueBytes = stringToBytes(value);
+ writeByteArray(valueBytes, TYPE_STRING);
+ return this;
+ }
+
+ /**
+ * Write a byte array field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeByteArray(@NonNull final byte[] value) {
+ // Write byte array typeId byte, followed by 4-byte representation of number of bytes
+ // in value, followed by the actual byte array.
+ writeByteArray(value, TYPE_BYTE_ARRAY);
+ return this;
+ }
+
+ private void writeByteArray(@NonNull final byte[] value, final byte typeId) {
+ writeTypeId(typeId);
+ final int numBytes = value.length;
+ mPos += mBuffer.putInt(mPos, numBytes);
+ mPos += mBuffer.putByteArray(mPos, value);
+ mNumElements++;
+ }
+
+ /**
+ * Write an attribution chain field to this StatsEvent.
+ *
+ * The sizes of uids and tags must be equal. The AttributionNode at position i is
+ * made up of uids[i] and tags[i].
+ *
+ * @param uids array of uids in the attribution nodes.
+ * @param tags array of tags in the attribution nodes.
+ **/
+ @NonNull
+ public Builder writeAttributionNode(
+ @NonNull final int[] uids, @NonNull final String[] tags) {
+ final byte numUids = (byte) uids.length;
+ final byte numTags = (byte) tags.length;
+
+ if (numUids != numTags) {
+ mErrorMask |= ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL;
+ } else if (numUids > MAX_ATTRIBUTION_NODES) {
+ mErrorMask |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG;
+ } else {
+ // Write attribution chain typeId byte, followed by 1-byte representation of
+ // number of attribution nodes, followed by encoding of each attribution node.
+ writeTypeId(TYPE_ATTRIBUTION_CHAIN);
+ mPos += mBuffer.putByte(mPos, numUids);
+ for (int i = 0; i < numUids; i++) {
+ // Each uid is encoded as 4-byte representation of its int value.
+ mPos += mBuffer.putInt(mPos, uids[i]);
+
+ // Each tag is encoded as 4-byte representation of number of bytes in its
+ // UTF-8 encoding, followed by the actual UTF-8 bytes.
+ final byte[] tagBytes = stringToBytes(tags[i]);
+ mPos += mBuffer.putInt(mPos, tagBytes.length);
+ mPos += mBuffer.putByteArray(mPos, tagBytes);
+ }
+ mNumElements++;
+ }
+ return this;
+ }
+
+ /**
+ * Write KeyValuePairsAtom entries to this StatsEvent.
+ *
+ * @param intMap Integer key-value pairs.
+ * @param longMap Long key-value pairs.
+ * @param stringMap String key-value pairs.
+ * @param floatMap Float key-value pairs.
+ **/
+ @NonNull
+ public Builder writeKeyValuePairs(
+ @NonNull final SparseIntArray intMap,
+ @NonNull final SparseLongArray longMap,
+ @NonNull final SparseArray<String> stringMap,
+ @NonNull final SparseArray<Float> floatMap) {
+ final int intMapSize = intMap.size();
+ final int longMapSize = longMap.size();
+ final int stringMapSize = stringMap.size();
+ final int floatMapSize = floatMap.size();
+ final int totalCount = intMapSize + longMapSize + stringMapSize + floatMapSize;
+
+ if (totalCount > MAX_KEY_VALUE_PAIRS) {
+ mErrorMask |= ERROR_TOO_MANY_KEY_VALUE_PAIRS;
+ } else {
+ writeTypeId(TYPE_KEY_VALUE_PAIRS);
+ mPos += mBuffer.putByte(mPos, (byte) totalCount);
+
+ for (int i = 0; i < intMapSize; i++) {
+ final int key = intMap.keyAt(i);
+ final int value = intMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_INT);
+ mPos += mBuffer.putInt(mPos, value);
+ }
+
+ for (int i = 0; i < longMapSize; i++) {
+ final int key = longMap.keyAt(i);
+ final long value = longMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_LONG);
+ mPos += mBuffer.putLong(mPos, value);
+ }
+
+ for (int i = 0; i < stringMapSize; i++) {
+ final int key = stringMap.keyAt(i);
+ final String value = stringMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_STRING);
+ final byte[] valueBytes = stringToBytes(value);
+ mPos += mBuffer.putInt(mPos, valueBytes.length);
+ mPos += mBuffer.putByteArray(mPos, valueBytes);
+ }
+
+ for (int i = 0; i < floatMapSize; i++) {
+ final int key = floatMap.keyAt(i);
+ final float value = floatMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_FLOAT);
+ mPos += mBuffer.putFloat(mPos, value);
+ }
+
+ mNumElements++;
+ }
+
+ return this;
+ }
+
+ /**
+ * Write a boolean annotation for the last field written.
+ **/
+ @NonNull
+ public Builder addBooleanAnnotation(
+ final byte annotationId, final boolean value) {
+ // Ensure there's a field written to annotate.
+ if (0 == mPosLastField) {
+ mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
+ } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) {
+ mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS;
+ } else {
+ mPos += mBuffer.putByte(mPos, annotationId);
+ mPos += mBuffer.putByte(mPos, TYPE_BOOLEAN);
+ mPos += mBuffer.putBoolean(mPos, value);
+ mCurrentAnnotationCount++;
+ writeAnnotationCount();
+ }
+ return this;
+ }
+
+ /**
+ * Write an integer annotation for the last field written.
+ **/
+ @NonNull
+ public Builder addIntAnnotation(final byte annotationId, final int value) {
+ if (0 == mPosLastField) {
+ mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
+ } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) {
+ mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS;
+ } else {
+ mPos += mBuffer.putByte(mPos, annotationId);
+ mPos += mBuffer.putByte(mPos, TYPE_INT);
+ mPos += mBuffer.putInt(mPos, value);
+ mCurrentAnnotationCount++;
+ writeAnnotationCount();
+ }
+ return this;
+ }
+
+ /**
+ * Builds a StatsEvent object with values entered in this Builder.
+ **/
+ @NonNull
+ public StatsEvent build() {
+ if (0L == mTimestampNs) {
+ mErrorMask |= ERROR_NO_TIMESTAMP;
+ }
+ if (0 == mAtomId) {
+ mErrorMask |= ERROR_NO_ATOM_ID;
+ }
+ if (mBuffer.hasOverflowed()) {
+ mErrorMask |= ERROR_OVERFLOW;
+ }
+ if (mNumElements > MAX_NUM_ELEMENTS) {
+ mErrorMask |= ERROR_TOO_MANY_FIELDS;
+ }
+
+ int size = mPos;
+ mPos = POS_TIMESTAMP_NS;
+ writeLong(mTimestampNs);
+ writeInt(mAtomId);
+ if (0 == mErrorMask) {
+ mBuffer.putByte(POS_NUM_ELEMENTS, (byte) mNumElements);
+ } else {
+ mBuffer.putByte(0, TYPE_ERRORS);
+ mBuffer.putByte(POS_NUM_ELEMENTS, (byte) 3);
+ mPos += mBuffer.putInt(mPos, mErrorMask);
+ size = mPos;
+ }
+
+ return new StatsEvent(mAtomId, mBuffer, size);
+ }
+
+ private void writeTypeId(final byte typeId) {
+ mPosLastField = mPos;
+ mLastType = typeId;
+ mCurrentAnnotationCount = 0;
+ final byte encodedId = (byte) (typeId & 0x0F);
+ mPos += mBuffer.putByte(mPos, encodedId);
+ }
+
+ private void writeAnnotationCount() {
+ // Use first 4 bits for annotation count and last 4 bits for typeId.
+ final byte encodedId = (byte) ((mCurrentAnnotationCount << 4) | (mLastType & 0x0F));
+ mBuffer.putByte(mPosLastField, encodedId);
+ }
+
+ @NonNull
+ private static byte[] stringToBytes(@Nullable final String value) {
+ return (null == value ? "" : value).getBytes(UTF_8);
+ }
+ }
+
+ private static final class Buffer {
+ private static Object sLock = new Object();
+
+ @GuardedBy("sLock")
+ private static Buffer sPool;
+
+ private final byte[] mBytes = new byte[MAX_PAYLOAD_SIZE];
+ private boolean mOverflow = false;
+
+ @NonNull
+ private static Buffer obtain() {
+ final Buffer buffer;
+ synchronized (sLock) {
+ buffer = null == sPool ? new Buffer() : sPool;
+ sPool = null;
+ }
+ buffer.reset();
+ return buffer;
+ }
+
+ private Buffer() {
+ }
+
+ @NonNull
+ private byte[] getBytes() {
+ return mBytes;
+ }
+
+ private void release() {
+ synchronized (sLock) {
+ if (null == sPool) {
+ sPool = this;
+ }
+ }
+ }
+
+ private void reset() {
+ mOverflow = false;
+ }
+
+ private boolean hasOverflowed() {
+ return mOverflow;
+ }
+
+ /**
+ * Checks for available space in the byte array.
+ *
+ * @param index starting position in the buffer to start the check.
+ * @param numBytes number of bytes to check from index.
+ * @return true if space is available, false otherwise.
+ **/
+ private boolean hasEnoughSpace(final int index, final int numBytes) {
+ final boolean result = index + numBytes < MAX_PAYLOAD_SIZE;
+ if (!result) {
+ mOverflow = true;
+ }
+ return result;
+ }
+
+ /**
+ * Writes a byte into the buffer.
+ *
+ * @param index position in the buffer where the byte is written.
+ * @param value the byte to write.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putByte(final int index, final byte value) {
+ if (hasEnoughSpace(index, Byte.BYTES)) {
+ mBytes[index] = (byte) (value);
+ return Byte.BYTES;
+ }
+ return 0;
+ }
+
+ /**
+ * Writes a boolean into the buffer.
+ *
+ * @param index position in the buffer where the boolean is written.
+ * @param value the boolean to write.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putBoolean(final int index, final boolean value) {
+ return putByte(index, (byte) (value ? 1 : 0));
+ }
+
+ /**
+ * Writes an integer into the buffer.
+ *
+ * @param index position in the buffer where the integer is written.
+ * @param value the integer to write.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putInt(final int index, final int value) {
+ if (hasEnoughSpace(index, Integer.BYTES)) {
+ // Use little endian byte order.
+ mBytes[index] = (byte) (value);
+ mBytes[index + 1] = (byte) (value >> 8);
+ mBytes[index + 2] = (byte) (value >> 16);
+ mBytes[index + 3] = (byte) (value >> 24);
+ return Integer.BYTES;
+ }
+ return 0;
+ }
+
+ /**
+ * Writes a long into the buffer.
+ *
+ * @param index position in the buffer where the long is written.
+ * @param value the long to write.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putLong(final int index, final long value) {
+ if (hasEnoughSpace(index, Long.BYTES)) {
+ // Use little endian byte order.
+ mBytes[index] = (byte) (value);
+ mBytes[index + 1] = (byte) (value >> 8);
+ mBytes[index + 2] = (byte) (value >> 16);
+ mBytes[index + 3] = (byte) (value >> 24);
+ mBytes[index + 4] = (byte) (value >> 32);
+ mBytes[index + 5] = (byte) (value >> 40);
+ mBytes[index + 6] = (byte) (value >> 48);
+ mBytes[index + 7] = (byte) (value >> 56);
+ return Long.BYTES;
+ }
+ return 0;
+ }
+
+ /**
+ * Writes a float into the buffer.
+ *
+ * @param index position in the buffer where the float is written.
+ * @param value the float to write.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putFloat(final int index, final float value) {
+ return putInt(index, Float.floatToIntBits(value));
+ }
+
+ /**
+ * Copies a byte array into the buffer.
+ *
+ * @param index position in the buffer where the byte array is copied.
+ * @param value the byte array to copy.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putByteArray(final int index, @NonNull final byte[] value) {
+ final int numBytes = value.length;
+ if (hasEnoughSpace(index, numBytes)) {
+ System.arraycopy(value, 0, mBytes, index, numBytes);
+ return numBytes;
+ }
+ return 0;
+ }
}
}
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index 8fbbcf4..d59ee92 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -145,7 +145,7 @@
boolean onSingleTapConfirmed(MotionEvent e);
/**
- * Notified when a double-tap occurs.
+ * Notified when a double-tap occurs. Triggered on the down event of second tap.
*
* @param e The down motion event of the first tap of the double-tap.
* @return true if the event is consumed, else false
@@ -378,7 +378,9 @@
*
* @param context the application's context
* @param listener the listener invoked for all the callbacks, this must
- * not be null.
+ * not be null. If the listener implements the {@link OnDoubleTapListener} or
+ * {@link OnContextClickListener} then it will also be set as the listener for
+ * these callbacks (for example when using the {@link SimpleOnGestureListener}).
*
* @throws NullPointerException if {@code listener} is null.
*/
@@ -393,7 +395,9 @@
*
* @param context the application's context
* @param listener the listener invoked for all the callbacks, this must
- * not be null.
+ * not be null. If the listener implements the {@link OnDoubleTapListener} or
+ * {@link OnContextClickListener} then it will also be set as the listener for
+ * these callbacks (for example when using the {@link SimpleOnGestureListener}).
* @param handler the handler to use for running deferred listener events.
*
* @throws NullPointerException if {@code listener} is null.
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index db01cea..37b9eb3 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -115,13 +115,11 @@
/**
* A haptic effect to signal the confirmation or successful completion of a user
* interaction.
- * @hide
*/
public static final int CONFIRM = 16;
/**
* A haptic effect to signal the rejection or failure of a user interaction.
- * @hide
*/
public static final int REJECT = 17;
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ComponentBinder.java b/core/java/android/view/IWindowContainer.aidl
similarity index 60%
copy from packages/SystemUI/src/com/android/systemui/dagger/ComponentBinder.java
copy to core/java/android/view/IWindowContainer.aidl
index 4e4c06e..878d86b 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ComponentBinder.java
+++ b/core/java/android/view/IWindowContainer.aidl
@@ -14,18 +14,19 @@
* limitations under the License.
*/
-package com.android.systemui.dagger;
+package android.view;
-import dagger.Binds;
-import dagger.Module;
+import android.view.SurfaceControl;
/**
- * Dagger Module that collects related sub-modules together.
+ * Interface for a window container to communicate with the window manager. This also acts as a
+ * token.
+ * @hide
*/
-@Module(includes = {ActivityBinder.class, ServiceBinder.class, SystemUIBinder.class})
-public abstract class ComponentBinder {
- /** */
- @Binds
- public abstract ContextComponentHelper bindComponentHelper(
- ContextComponentResolver componentHelper);
+interface IWindowContainer {
+
+ /**
+ * Gets a persistent leash for this container or {@code null}.
+ */
+ SurfaceControl getLeash();
}
diff --git a/core/java/android/view/InputChannel.java b/core/java/android/view/InputChannel.java
index 831e9ee..5d0d5bd 100644
--- a/core/java/android/view/InputChannel.java
+++ b/core/java/android/view/InputChannel.java
@@ -61,7 +61,6 @@
private native void nativeWriteToParcel(Parcel parcel);
private native void nativeDup(InputChannel target);
private native IBinder nativeGetToken();
- private native void nativeSetToken(IBinder token);
private native String nativeGetName();
@@ -185,8 +184,4 @@
public IBinder getToken() {
return nativeGetToken();
}
-
- public void setToken(IBinder token) {
- nativeSetToken(token);
- }
}
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 0175ba2..5876b03 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
@@ -139,7 +140,7 @@
*
* @param context The context to associate this view with.
*/
- public TextureView(Context context) {
+ public TextureView(@NonNull Context context) {
super(context);
}
@@ -149,7 +150,7 @@
* @param context The context to associate this view with.
* @param attrs The attributes of the XML tag that is inflating the view.
*/
- public TextureView(Context context, AttributeSet attrs) {
+ public TextureView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@@ -162,7 +163,7 @@
* reference to a style resource that supplies default values for
* the view. Can be 0 to not look for defaults.
*/
- public TextureView(Context context, AttributeSet attrs, int defStyleAttr) {
+ public TextureView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@@ -179,7 +180,8 @@
* defStyleAttr is 0 or can not be found in the theme. Can be 0
* to not look for defaults.
*/
- public TextureView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ public TextureView(@NonNull Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@@ -484,13 +486,13 @@
* situations, make sure this texture view is not marked opaque.</p>
*
* @param transform The transform to apply to the content of
- * this view.
+ * this view. If null the transform will be set to identity.
*
* @see #getTransform(android.graphics.Matrix)
* @see #isOpaque()
* @see #setOpaque(boolean)
*/
- public void setTransform(Matrix transform) {
+ public void setTransform(@Nullable Matrix transform) {
mMatrix.set(transform);
mMatrixChanged = true;
invalidateParentIfNeeded();
@@ -507,7 +509,7 @@
*
* @see #setTransform(android.graphics.Matrix)
*/
- public Matrix getTransform(Matrix transform) {
+ public @NonNull Matrix getTransform(@Nullable Matrix transform) {
if (transform == null) {
transform = new Matrix();
}
@@ -544,7 +546,7 @@
* @see #getBitmap(android.graphics.Bitmap)
* @see #getBitmap(int, int)
*/
- public Bitmap getBitmap() {
+ public @Nullable Bitmap getBitmap() {
return getBitmap(getWidth(), getHeight());
}
@@ -571,7 +573,7 @@
* @see #getBitmap(android.graphics.Bitmap)
* @see #getBitmap()
*/
- public Bitmap getBitmap(int width, int height) {
+ public @Nullable Bitmap getBitmap(int width, int height) {
if (isAvailable() && width > 0 && height > 0) {
return getBitmap(Bitmap.createBitmap(getResources().getDisplayMetrics(),
width, height, Bitmap.Config.ARGB_8888));
@@ -602,7 +604,7 @@
* @throws IllegalStateException if the hardware rendering context cannot be
* acquired to capture the bitmap
*/
- public Bitmap getBitmap(Bitmap bitmap) {
+ public @NonNull Bitmap getBitmap(@NonNull Bitmap bitmap) {
if (bitmap != null && isAvailable()) {
applyUpdate();
applyTransformMatrix();
@@ -649,12 +651,13 @@
* owned by another producer. For instance, if the TextureView is being used
* to render the camera's preview you cannot invoke this method.</p>
*
- * @return A Canvas used to draw into the surface.
+ * @return A Canvas used to draw into the surface, or null if the surface cannot be locked for
+ * drawing (see {@link #isAvailable()}).
*
* @see #lockCanvas(android.graphics.Rect)
* @see #unlockCanvasAndPost(android.graphics.Canvas)
*/
- public Canvas lockCanvas() {
+ public @Nullable Canvas lockCanvas() {
return lockCanvas(null);
}
@@ -669,15 +672,17 @@
* already connected to an image producer (for instance: the camera,
* OpenGL, a media player, etc.)
*
- * @param dirty Area of the surface that will be modified.
+ * @param dirty Area of the surface that will be modified. If null the area of the entire
+ * surface is used.
- * @return A Canvas used to draw into the surface.
+ * @return A Canvas used to draw into the surface, or null if the surface cannot be locked for
+ * drawing (see {@link #isAvailable()}).
*
* @see #lockCanvas()
* @see #unlockCanvasAndPost(android.graphics.Canvas)
* @see #isAvailable()
*/
- public Canvas lockCanvas(Rect dirty) {
+ public @Nullable Canvas lockCanvas(@Nullable Rect dirty) {
if (!isAvailable()) return null;
if (mCanvas == null) {
@@ -705,7 +710,7 @@
* @see #lockCanvas()
* @see #lockCanvas(android.graphics.Rect)
*/
- public void unlockCanvasAndPost(Canvas canvas) {
+ public void unlockCanvasAndPost(@NonNull Canvas canvas) {
if (mCanvas != null && canvas == mCanvas) {
canvas.restoreToCount(mSaveCount);
mSaveCount = 0;
@@ -723,7 +728,7 @@
*
* @see #isAvailable()
*/
- public SurfaceTexture getSurfaceTexture() {
+ public @Nullable SurfaceTexture getSurfaceTexture() {
return mSurface;
}
@@ -742,7 +747,7 @@
* @param surfaceTexture The {@link SurfaceTexture} that the view should use.
* @see SurfaceTexture#detachFromGLContext()
*/
- public void setSurfaceTexture(SurfaceTexture surfaceTexture) {
+ public void setSurfaceTexture(@NonNull SurfaceTexture surfaceTexture) {
if (surfaceTexture == null) {
throw new NullPointerException("surfaceTexture must not be null");
}
@@ -781,7 +786,7 @@
* @see #setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener)
* @see SurfaceTextureListener
*/
- public SurfaceTextureListener getSurfaceTextureListener() {
+ public @Nullable SurfaceTextureListener getSurfaceTextureListener() {
return mListener;
}
@@ -792,25 +797,22 @@
* @see #getSurfaceTextureListener()
* @see SurfaceTextureListener
*/
- public void setSurfaceTextureListener(SurfaceTextureListener listener) {
+ public void setSurfaceTextureListener(@Nullable SurfaceTextureListener listener) {
mListener = listener;
}
@UnsupportedAppUsage
private final SurfaceTexture.OnFrameAvailableListener mUpdateListener =
- new SurfaceTexture.OnFrameAvailableListener() {
- @Override
- public void onFrameAvailable(SurfaceTexture surfaceTexture) {
- updateLayer();
- invalidate();
- }
- };
+ surfaceTexture -> {
+ updateLayer();
+ invalidate();
+ };
/**
* This listener can be used to be notified when the surface texture
* associated with this texture view is available.
*/
- public static interface SurfaceTextureListener {
+ public interface SurfaceTextureListener {
/**
* Invoked when a {@link TextureView}'s SurfaceTexture is ready for use.
*
@@ -819,7 +821,7 @@
* @param width The width of the surface
* @param height The height of the surface
*/
- public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height);
+ void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height);
/**
* Invoked when the {@link SurfaceTexture}'s buffers size changed.
@@ -829,7 +831,7 @@
* @param width The new width of the surface
* @param height The new height of the surface
*/
- public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height);
+ void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height);
/**
* Invoked when the specified {@link SurfaceTexture} is about to be destroyed.
@@ -839,7 +841,7 @@
*
* @param surface The surface about to be destroyed
*/
- public boolean onSurfaceTextureDestroyed(SurfaceTexture surface);
+ boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface);
/**
* Invoked when the specified {@link SurfaceTexture} is updated through
@@ -847,7 +849,7 @@
*
* @param surface The surface just updated
*/
- public void onSurfaceTextureUpdated(SurfaceTexture surface);
+ void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface);
}
@UnsupportedAppUsage
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1599afb..412b0ca 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -493,7 +493,7 @@
*
* <p>
* To initiate a layout, call {@link #requestLayout}. This method is typically
- * called by a view on itself when it believes that is can no longer fit within
+ * called by a view on itself when it believes that it can no longer fit within
* its current bounds.
* </p>
*
@@ -2836,7 +2836,7 @@
/**
* Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
- * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
+ * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph's text direction.
*
* Use with {@link #setTextAlignment(int)}
*/
@@ -2864,7 +2864,7 @@
public static final int TEXT_ALIGNMENT_CENTER = 4;
/**
- * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
+ * Align to the start of the view, which is ALIGN_LEFT if the view's resolved
* layoutDirection is LTR, and ALIGN_RIGHT otherwise.
*
* Use with {@link #setTextAlignment(int)}
@@ -2872,7 +2872,7 @@
public static final int TEXT_ALIGNMENT_VIEW_START = 5;
/**
- * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
+ * Align to the end of the view, which is ALIGN_RIGHT if the view's resolved
* layoutDirection is LTR, and ALIGN_LEFT otherwise.
*
* Use with {@link #setTextAlignment(int)}
@@ -3675,7 +3675,7 @@
* if the user swipes from the top of the screen.
* <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
* system gestures, such as swiping from the top of the screen. These transient system bars
- * will overlay app’s content, may have some degree of transparency, and will automatically
+ * will overlay app's content, may have some degree of transparency, and will automatically
* hide after a short timeout.
* </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
* {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
@@ -8727,7 +8727,7 @@
structure.setContextClickable(true);
}
structure.setClassName(getAccessibilityClassName().toString());
- structure.setContentDescription(getContentDescription());
+ structure.setContentDescription(mContentDescription);
}
/**
@@ -9934,8 +9934,8 @@
info.setImportantForAccessibility(isImportantForAccessibility());
info.setPackageName(mContext.getPackageName());
info.setClassName(getAccessibilityClassName());
- info.setStateDescription(getStateDescription());
- info.setContentDescription(getContentDescription());
+ info.setStateDescription(mStateDescription);
+ info.setContentDescription(mContentDescription);
info.setEnabled(isEnabled());
info.setClickable(isClickable());
@@ -10295,7 +10295,7 @@
}
/**
- * Gets the unique identifier of the window in which this View reseides.
+ * Gets the unique identifier of the window in which this View resides.
*
* @return The window accessibility id.
*
@@ -10318,7 +10318,7 @@
* @see #setStateDescription(CharSequence)
*/
@ViewDebug.ExportedProperty(category = "accessibility")
- public final @Nullable CharSequence getStateDescription() {
+ public @Nullable CharSequence getStateDescription() {
return mStateDescription;
}
@@ -13724,7 +13724,7 @@
*/
@UnsupportedAppUsage
public CharSequence getIterableTextForAccessibility() {
- return getContentDescription();
+ return mContentDescription;
}
/**
@@ -29514,9 +29514,10 @@
stream.addProperty("text:textAlignment", getTextAlignment());
// accessibility
- CharSequence contentDescription = getContentDescription();
stream.addProperty("accessibility:contentDescription",
- contentDescription == null ? "" : contentDescription.toString());
+ mContentDescription == null ? "" : mContentDescription.toString());
+ stream.addProperty("accessibility:stateDescription",
+ mStateDescription == null ? "" : mStateDescription.toString());
stream.addProperty("accessibility:labelFor", getLabelFor());
stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
}
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 9e914d4..6a099d57 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -23,7 +23,6 @@
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.graphics.Point;
import android.os.Build;
import android.os.RemoteException;
import android.provider.Settings;
@@ -398,11 +397,7 @@
mWindowTouchSlop = (int) (sizeAndDensity * WINDOW_TOUCH_SLOP + 0.5f);
// Size of the screen in bytes, in ARGB_8888 format
- final WindowManager win = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
- final Display display = win.getDefaultDisplay();
- final Point size = new Point();
- display.getRealSize(size);
- mMaximumDrawingCacheSize = 4 * size.x * size.y;
+ mMaximumDrawingCacheSize = 4 * metrics.heightPixels * metrics.widthPixels;
mOverscrollDistance = (int) (sizeAndDensity * OVERSCROLL_DISTANCE + 0.5f);
mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f);
@@ -842,6 +837,7 @@
* The maximum drawing cache size expressed in bytes.
*
* @return the maximum size of View's drawing cache expressed in bytes
+ *
*/
public int getScaledMaximumDrawingCacheSize() {
return mMaximumDrawingCacheSize;
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index ad59ae5..36daa5c 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -945,6 +945,94 @@
return null;
}
+ private static class StreamingPictureCallbackHandler implements AutoCloseable,
+ HardwareRenderer.PictureCapturedCallback, Runnable {
+ private final HardwareRenderer mRenderer;
+ private final Callable<OutputStream> mCallback;
+ private final Executor mExecutor;
+ private final ReentrantLock mLock = new ReentrantLock(false);
+ private final ArrayDeque<byte[]> mQueue = new ArrayDeque<>(3);
+ private final ByteArrayOutputStream mByteStream = new ByteArrayOutputStream();
+ private boolean mStopListening;
+ private Thread mRenderThread;
+
+ private StreamingPictureCallbackHandler(HardwareRenderer renderer,
+ Callable<OutputStream> callback, Executor executor) {
+ mRenderer = renderer;
+ mCallback = callback;
+ mExecutor = executor;
+ mRenderer.setPictureCaptureCallback(this);
+ }
+
+ @Override
+ public void close() {
+ mLock.lock();
+ mStopListening = true;
+ mLock.unlock();
+ mRenderer.setPictureCaptureCallback(null);
+ }
+
+ @Override
+ public void onPictureCaptured(Picture picture) {
+ mLock.lock();
+ if (mStopListening) {
+ mLock.unlock();
+ mRenderer.setPictureCaptureCallback(null);
+ return;
+ }
+ if (mRenderThread == null) {
+ mRenderThread = Thread.currentThread();
+ }
+ boolean needsInvoke = true;
+ if (mQueue.size() == 3) {
+ mQueue.removeLast();
+ needsInvoke = false;
+ }
+ picture.writeToStream(mByteStream);
+ mQueue.add(mByteStream.toByteArray());
+ mByteStream.reset();
+ mLock.unlock();
+
+ if (needsInvoke) {
+ mExecutor.execute(this);
+ }
+ }
+
+ @Override
+ public void run() {
+ mLock.lock();
+ final byte[] picture = mQueue.poll();
+ final boolean isStopped = mStopListening;
+ mLock.unlock();
+ if (Thread.currentThread() == mRenderThread) {
+ close();
+ throw new IllegalStateException(
+ "ViewDebug#startRenderingCommandsCapture must be given an executor that "
+ + "invokes asynchronously");
+ }
+ if (isStopped) {
+ return;
+ }
+ OutputStream stream = null;
+ try {
+ stream = mCallback.call();
+ } catch (Exception ex) {
+ Log.w("ViewDebug", "Aborting rendering commands capture "
+ + "because callback threw exception", ex);
+ }
+ if (stream != null) {
+ try {
+ stream.write(picture);
+ } catch (IOException ex) {
+ Log.w("ViewDebug", "Aborting rendering commands capture "
+ + "due to IOException writing to output stream", ex);
+ }
+ } else {
+ close();
+ }
+ }
+ }
+
/**
* Begins capturing the entire rendering commands for the view tree referenced by the given
* view. The view passed may be any View in the tree as long as it is attached. That is,
@@ -990,18 +1078,7 @@
}
final HardwareRenderer renderer = attachInfo.mThreadedRenderer;
if (renderer != null) {
- return new PictureCallbackHandler(renderer, (picture -> {
- try {
- OutputStream stream = callback.call();
- if (stream != null) {
- picture.writeToStream(stream);
- return true;
- }
- } catch (Exception ex) {
- // fall through
- }
- return false;
- }), executor);
+ return new StreamingPictureCallbackHandler(renderer, callback, executor);
}
return null;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 20dc234..85bf19f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -439,7 +439,6 @@
boolean mReportNextDraw;
boolean mFullRedrawNeeded;
boolean mNewSurfaceNeeded;
- boolean mHasHadWindowFocus;
boolean mLastWasImTarget;
boolean mForceNextWindowRelayout;
CountDownLatch mWindowDrawCountDown;
@@ -2123,11 +2122,6 @@
endDragResizing();
destroyHardwareResources();
}
- if (viewVisibility == View.GONE) {
- // After making a window gone, we will count it as being
- // shown for the first time the next time it gets focus.
- mHasHadWindowFocus = false;
- }
}
// Non-visible windows can't hold accessibility focus.
@@ -2823,8 +2817,7 @@
if (imm != null && imTarget) {
imm.onPreWindowFocus(mView, hasWindowFocus);
imm.onPostWindowFocus(mView, mView.findFocus(),
- mWindowAttributes.softInputMode,
- !mHasHadWindowFocus, mWindowAttributes.flags);
+ mWindowAttributes.softInputMode, mWindowAttributes.flags);
}
}
}
@@ -3017,8 +3010,7 @@
if (hasWindowFocus) {
if (imm != null && mLastWasImTarget && !isInLocalFocusMode()) {
imm.onPostWindowFocus(mView, mView.findFocus(),
- mWindowAttributes.softInputMode,
- !mHasHadWindowFocus, mWindowAttributes.flags);
+ mWindowAttributes.softInputMode, mWindowAttributes.flags);
}
// Clear the forward bit. We can just do this directly, since
// the window manager doesn't care about it.
@@ -3028,7 +3020,6 @@
.softInputMode &=
~WindowManager.LayoutParams
.SOFT_INPUT_IS_FORWARD_NAVIGATION;
- mHasHadWindowFocus = true;
// Refocusing a window that has a focused view should fire a
// focus event for the view since the global focused view changed.
diff --git a/core/java/android/view/WindowContainerTransaction.aidl b/core/java/android/view/WindowContainerTransaction.aidl
new file mode 100644
index 0000000..46ba6c1
--- /dev/null
+++ b/core/java/android/view/WindowContainerTransaction.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+parcelable WindowContainerTransaction;
diff --git a/core/java/android/view/WindowContainerTransaction.java b/core/java/android/view/WindowContainerTransaction.java
new file mode 100644
index 0000000..607a870
--- /dev/null
+++ b/core/java/android/view/WindowContainerTransaction.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.app.WindowConfiguration;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import java.util.Map;
+
+/**
+ * Represents a collection of operations on some WindowContainers that should be applied all at
+ * once.
+ *
+ * @hide
+ */
+public class WindowContainerTransaction implements Parcelable {
+ private final ArrayMap<IBinder, Change> mChanges = new ArrayMap<>();
+
+ public WindowContainerTransaction() {}
+
+ protected WindowContainerTransaction(Parcel in) {
+ in.readMap(mChanges, null /* loader */);
+ }
+
+ private Change getOrCreateChange(IBinder token) {
+ Change out = mChanges.get(token);
+ if (out == null) {
+ out = new Change();
+ mChanges.put(token, out);
+ }
+ return out;
+ }
+
+ /**
+ * Resize a container.
+ */
+ public WindowContainerTransaction setBounds(IWindowContainer container, Rect bounds) {
+ Change chg = getOrCreateChange(container.asBinder());
+ chg.mConfiguration.windowConfiguration.setBounds(bounds);
+ chg.mConfigSetMask |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
+ chg.mWindowSetMask |= WindowConfiguration.WINDOW_CONFIG_BOUNDS;
+ return this;
+ }
+
+ public Map<IBinder, Change> getChanges() {
+ return mChanges;
+ }
+
+ @Override
+ public String toString() {
+ return "WindowContainerTransaction { changes = " + mChanges + " }";
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeMap(mChanges);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<WindowContainerTransaction> CREATOR =
+ new Creator<WindowContainerTransaction>() {
+ @Override
+ public WindowContainerTransaction createFromParcel(Parcel in) {
+ return new WindowContainerTransaction(in);
+ }
+
+ @Override
+ public WindowContainerTransaction[] newArray(int size) {
+ return new WindowContainerTransaction[size];
+ }
+ };
+
+ /**
+ * Holds changes on a single WindowContainer including Configuration changes.
+ *
+ * @hide
+ */
+ public static class Change implements Parcelable {
+ private final Configuration mConfiguration = new Configuration();
+ private @ActivityInfo.Config int mConfigSetMask = 0;
+ private @WindowConfiguration.WindowConfig int mWindowSetMask = 0;
+
+ public Change() {}
+
+ protected Change(Parcel in) {
+ mConfiguration.readFromParcel(in);
+ mConfigSetMask = in.readInt();
+ mWindowSetMask = in.readInt();
+ }
+
+ public Configuration getConfiguration() {
+ return mConfiguration;
+ }
+
+ @ActivityInfo.Config
+ public int getConfigSetMask() {
+ return mConfigSetMask;
+ }
+
+ @WindowConfiguration.WindowConfig
+ public int getWindowSetMask() {
+ return mWindowSetMask;
+ }
+
+ @Override
+ public String toString() {
+ final boolean changesBounds =
+ (mConfigSetMask & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0
+ && ((mWindowSetMask & WindowConfiguration.WINDOW_CONFIG_BOUNDS)
+ != 0);
+ final boolean changesSss =
+ (mConfigSetMask & ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE) != 0;
+ StringBuilder sb = new StringBuilder();
+ sb.append('{');
+ if (changesBounds) {
+ sb.append("bounds:" + mConfiguration.windowConfiguration.getBounds() + ",");
+ }
+ if (changesSss) {
+ sb.append("ssw:" + mConfiguration.smallestScreenWidthDp + ",");
+ }
+ sb.append("}");
+ return sb.toString();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ mConfiguration.writeToParcel(dest, flags);
+ dest.writeInt(mConfigSetMask);
+ dest.writeInt(mWindowSetMask);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<Change> CREATOR = new Creator<Change>() {
+ @Override
+ public Change createFromParcel(Parcel in) {
+ return new Change(in);
+ }
+
+ @Override
+ public Change[] newArray(int size) {
+ return new Change[size];
+ }
+ };
+ }
+}
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index f4f7d0b..6c6046f 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -93,8 +93,9 @@
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
InsetsState outInsetsState) {
final SurfaceControl.Builder b = new SurfaceControl.Builder(mSurfaceSession)
- .setParent(mRootSurface)
- .setName(attrs.getTitle().toString());
+ .setParent(mRootSurface)
+ .setFormat(attrs.format)
+ .setName(attrs.getTitle().toString());
final SurfaceControl sc = b.build();
synchronized (this) {
mStateForWindow.put(window.asBinder(), new State(sc, attrs));
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index c877b9c..f5b0746 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -127,7 +127,7 @@
*
* @param context Application context used to access resources
* @param id The resource id of the animation to load
- * @return The animation object reference by the specified id
+ * @return The animation object referenced by the specified id
* @throws NotFoundException when the animation cannot be loaded
*/
public static Animation loadAnimation(Context context, @AnimRes int id)
@@ -208,7 +208,7 @@
*
* @param context Application context used to access resources
* @param id The resource id of the animation to load
- * @return The animation object reference by the specified id
+ * @return The animation controller object referenced by the specified id
* @throws NotFoundException when the layout animation controller cannot be loaded
*/
public static LayoutAnimationController loadLayoutAnimation(Context context, @AnimRes int id)
@@ -331,7 +331,7 @@
*
* @param context Application context used to access resources
* @param id The resource id of the animation to load
- * @return The animation object reference by the specified id
+ * @return The interpolator object referenced by the specified id
* @throws NotFoundException
*/
public static Interpolator loadInterpolator(Context context, @AnimRes @InterpolatorRes int id)
@@ -361,7 +361,7 @@
*
* @param res The resources
* @param id The resource id of the animation to load
- * @return The interpolator object reference by the specified id
+ * @return The interpolator object referenced by the specified id
* @throws NotFoundException
* @hide
*/
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 3bbd321..54446e1 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -208,6 +208,10 @@
public static final String EXTRA_RESTORE_SESSION_TOKEN =
"android.view.autofill.extra.RESTORE_SESSION_TOKEN";
+ /** @hide */
+ public static final String EXTRA_RESTORE_CROSS_ACTIVITY =
+ "android.view.autofill.extra.RESTORE_CROSS_ACTIVITY";
+
/**
* Internal extra used to pass a binder to the {@link IAugmentedAutofillManagerClient}.
*
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 6420d71..e81db16 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -92,7 +92,10 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
@@ -358,7 +361,7 @@
boolean mActive = false;
/**
- * {@code true} if next {@link #onPostWindowFocus(View, View, int, boolean, int)} needs to
+ * {@code true} if next {@link #onPostWindowFocus(View, View, int, int)} needs to
* restart input.
*/
boolean mRestartOnNextWindowFocus = true;
@@ -422,6 +425,13 @@
int mCursorCandEnd;
/**
+ * Initial startInput with {@link StartInputReason.WINDOW_FOCUS_GAIN} is executed
+ * in a background thread. Later, if there is an actual startInput it will wait on
+ * main thread till the background thread completes.
+ */
+ private CompletableFuture<Void> mWindowFocusGainFuture;
+
+ /**
* The instance that has previously been sent to the input method.
*/
private CursorAnchorInfo mCursorAnchorInfo = null;
@@ -1598,6 +1608,18 @@
boolean startInputInner(@StartInputReason int startInputReason,
@Nullable IBinder windowGainingFocus, @StartInputFlags int startInputFlags,
@SoftInputModeFlags int softInputMode, int windowFlags) {
+ if (startInputReason != StartInputReason.WINDOW_FOCUS_GAIN
+ && mWindowFocusGainFuture != null) {
+ try {
+ mWindowFocusGainFuture.get();
+ } catch (ExecutionException | InterruptedException e) {
+ // do nothing
+ } catch (CancellationException e) {
+ // window no longer has focus.
+ return true;
+ }
+ }
+
final View view;
synchronized (mH) {
view = mServedView;
@@ -1925,13 +1947,12 @@
* @hide
*/
public void onPostWindowFocus(View rootView, View focusedView,
- @SoftInputModeFlags int softInputMode, boolean first, int windowFlags) {
+ @SoftInputModeFlags int softInputMode, int windowFlags) {
boolean forceNewFocus = false;
synchronized (mH) {
if (DEBUG) Log.v(TAG, "onWindowFocus: " + focusedView
+ " softInputMode=" + InputMethodDebug.softInputModeToString(softInputMode)
- + " first=" + first + " flags=#"
- + Integer.toHexString(windowFlags));
+ + " flags=#" + Integer.toHexString(windowFlags));
if (mRestartOnNextWindowFocus) {
if (DEBUG) Log.v(TAG, "Restarting due to mRestartOnNextWindowFocus");
mRestartOnNextWindowFocus = false;
@@ -1947,35 +1968,39 @@
startInputFlags |= StartInputFlags.IS_TEXT_EDITOR;
}
}
- if (first) {
- startInputFlags |= StartInputFlags.FIRST_WINDOW_FOCUS_GAIN;
- }
- if (checkFocusNoStartInput(forceNewFocus)) {
- // We need to restart input on the current focus view. This
- // should be done in conjunction with telling the system service
- // about the window gaining focus, to help make the transition
- // smooth.
- if (startInputInner(StartInputReason.WINDOW_FOCUS_GAIN, rootView.getWindowToken(),
- startInputFlags, softInputMode, windowFlags)) {
- return;
- }
+ final boolean forceNewFocus1 = forceNewFocus;
+ final int startInputFlags1 = startInputFlags;
+ if (mWindowFocusGainFuture != null) {
+ mWindowFocusGainFuture.cancel(false/* mayInterruptIfRunning */);
}
+ mWindowFocusGainFuture = CompletableFuture.runAsync(() -> {
+ if (checkFocusNoStartInput(forceNewFocus1)) {
+ // We need to restart input on the current focus view. This
+ // should be done in conjunction with telling the system service
+ // about the window gaining focus, to help make the transition
+ // smooth.
+ if (startInputInner(StartInputReason.WINDOW_FOCUS_GAIN, rootView.getWindowToken(),
+ startInputFlags1, softInputMode, windowFlags)) {
+ return;
+ }
+ }
- // For some reason we didn't do a startInput + windowFocusGain, so
- // we'll just do a window focus gain and call it a day.
- synchronized (mH) {
- try {
- if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
- mService.startInputOrWindowGainedFocus(
- StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
- rootView.getWindowToken(), startInputFlags, softInputMode, windowFlags,
- null, null, 0 /* missingMethodFlags */,
- rootView.getContext().getApplicationInfo().targetSdkVersion);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ // For some reason we didn't do a startInput + windowFocusGain, so
+ // we'll just do a window focus gain and call it a day.
+ synchronized (mH) {
+ try {
+ if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
+ mService.startInputOrWindowGainedFocus(
+ StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
+ rootView.getWindowToken(), startInputFlags1, softInputMode, windowFlags,
+ null, null, 0 /* missingMethodFlags */,
+ rootView.getContext().getApplicationInfo().targetSdkVersion);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
- }
+ });
}
/** @hide */
@@ -1990,6 +2015,10 @@
// If the mCurRootView is losing window focus, release the strong reference to it
// so as not to prevent it from being garbage-collected.
mCurRootView = null;
+ if (mWindowFocusGainFuture != null) {
+ mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */);
+ mWindowFocusGainFuture = null;
+ }
} else {
if (DEBUG) {
Log.v(TAG, "Ignoring onPreWindowFocus()."
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index 23d1237..3824c22 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -22,7 +22,10 @@
/**
* Manages the cookies used by an application's {@link WebView} instances.
- * Cookies are manipulated according to RFC2109.
+ * <p>
+ * CookieManager represents cookies as strings in the same format as the
+ * HTTP {@code Cookie} and {@code Set-Cookie} header fields (defined in
+ * <a href="https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03">RFC6265bis</a>).
*/
public abstract class CookieManager {
/**
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 7282008..2895621 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -328,6 +328,9 @@
* <p>
* The built-in mechanisms are the only currently supported zoom
* mechanisms, so it is recommended that this setting is always enabled.
+ * However, on-screen zoom controls are deprecated in Android (see
+ * {@link android.widget.ZoomButtonsController}) so it's recommended to
+ * disable {@link #setDisplayZoomControls}.
*
* @param enabled whether the WebView should use its built-in zoom mechanisms
*/
@@ -347,7 +350,9 @@
/**
* Sets whether the WebView should display on-screen zoom controls when
* using the built-in zoom mechanisms. See {@link #setBuiltInZoomControls}.
- * The default is {@code true}.
+ * The default is {@code true}. However, on-screen zoom controls are deprecated
+ * in Android (see {@link android.widget.ZoomButtonsController}) so it's
+ * recommended to set this to {@code false}.
*
* @param enabled whether the WebView should display on-screen zoom controls
*/
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 57ce28e..27402a4 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1189,6 +1189,9 @@
}
public boolean performLongClick(boolean handled) {
+ if (TextView.DEBUG_CURSOR) {
+ logCursor("performLongClick", "handled=%s", handled);
+ }
// Long press in empty space moves cursor and starts the insertion action mode.
if (!handled && !isPositionOnText(mLastDownPositionX, mLastDownPositionY)
&& mInsertionControllerEnabled) {
@@ -1252,6 +1255,10 @@
}
void onFocusChanged(boolean focused, int direction) {
+ if (TextView.DEBUG_CURSOR) {
+ logCursor("onFocusChanged", "focused=%s", focused);
+ }
+
mShowCursor = SystemClock.uptimeMillis();
ensureEndedBatchEdit();
@@ -1450,12 +1457,22 @@
} else {
mTapState = TAP_STATE_TRIPLE_CLICK;
}
+ if (TextView.DEBUG_CURSOR) {
+ logCursor("updateTapState", "ACTION_DOWN: %s tap detected",
+ (mTapState == TAP_STATE_DOUBLE_TAP ? "double" : "triple"));
+ }
} else {
mTapState = TAP_STATE_FIRST_TAP;
+ if (TextView.DEBUG_CURSOR) {
+ logCursor("updateTapState", "ACTION_DOWN: first tap detected");
+ }
}
}
if (action == MotionEvent.ACTION_UP) {
mLastTouchUpTime = SystemClock.uptimeMillis();
+ if (TextView.DEBUG_CURSOR) {
+ logCursor("updateTapState", "ACTION_UP");
+ }
}
}
@@ -2354,6 +2371,9 @@
}
void onTouchUpEvent(MotionEvent event) {
+ if (TextView.DEBUG_CURSOR) {
+ logCursor("onTouchUpEvent", null);
+ }
if (getSelectionActionModeHelper().resetSelection(
getTextView().getOffsetForPosition(event.getX(), event.getY()))) {
return;
@@ -2481,6 +2501,9 @@
loadCursorDrawable();
final int left = clampHorizontalPosition(mDrawableForCursor, horizontal);
final int width = mDrawableForCursor.getIntrinsicWidth();
+ if (TextView.DEBUG_CURSOR) {
+ logCursor("updateCursorPosition", "left=%s, top=%s", left, (top - mTempRect.top));
+ }
mDrawableForCursor.setBounds(left, top - mTempRect.top, left + width,
bottom + mTempRect.bottom);
}
@@ -4621,6 +4644,11 @@
}
public void show() {
+ if (TextView.DEBUG_CURSOR) {
+ logCursor(getClass().getSimpleName() + ": HandleView: show()", "offset=%s",
+ getCurrentCursorOffset());
+ }
+
if (isShowing()) return;
getPositionListener().addSubscriber(this, true /* local position may change */);
@@ -4637,6 +4665,11 @@
}
public void hide() {
+ if (TextView.DEBUG_CURSOR) {
+ logCursor(getClass().getSimpleName() + ": HandleView: hide()", "offset=%s",
+ getCurrentCursorOffset());
+ }
+
dismiss();
getPositionListener().removeSubscriber(this);
@@ -5033,6 +5066,11 @@
@Override
public boolean onTouchEvent(MotionEvent ev) {
+ if (TextView.DEBUG_CURSOR) {
+ logCursor(this.getClass().getSimpleName() + ": HandleView: onTouchEvent",
+ MotionEvent.actionToString(ev.getActionMasked()));
+ }
+
updateFloatingToolbarVisibility(ev);
switch (ev.getActionMasked()) {
@@ -5951,6 +5989,10 @@
distanceSquared < doubleTapSlop * doubleTapSlop;
if (stayedInArea && (isMouse || isPositionOnText(eventX, eventY))) {
+ if (TextView.DEBUG_CURSOR) {
+ logCursor("SelectionModifierCursorController: onTouchEvent",
+ "ACTION_DOWN: select and start drag");
+ }
if (mTapState == TAP_STATE_DOUBLE_TAP) {
selectCurrentWordAndStartDrag();
} else if (mTapState == TAP_STATE_TRIPLE_CLICK) {
@@ -6028,6 +6070,9 @@
break;
case MotionEvent.ACTION_UP:
+ if (TextView.DEBUG_CURSOR) {
+ logCursor("SelectionModifierCursorController: onTouchEvent", "ACTION_UP");
+ }
if (!isDragAcceleratorActive()) {
break;
}
@@ -7119,4 +7164,12 @@
return resolveInfo.loadLabel(mPackageManager);
}
}
+
+ private static void logCursor(String location, @Nullable String msgFormat, Object ... msgArgs) {
+ if (msgFormat == null) {
+ Log.d(TAG, location);
+ } else {
+ Log.d(TAG, location + ": " + String.format(msgFormat, msgArgs));
+ }
+ }
}
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 1cb1148..3a197e2 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -120,10 +120,6 @@
* <a href="{@docRoot}training/improving-layouts/smooth-scrolling.html">
* Making ListView Scrolling Smooth</a> for more ways to ensure a smooth user experience.</p>
*
- * <p>For a more complete example of creating a custom adapter, see the
- * <a href="{@docRoot}samples/CustomChoiceList/index.html">
- * Custom Choice List</a> sample app.</p>
- *
* <p>To specify an action when a user clicks or taps on a single list item, see
* <a href="{@docRoot}guide/topics/ui/declaring-layout.html#HandlingUserSelections">
* Handling click events</a>.</p>
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 2e95743..d58d858 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -163,7 +163,6 @@
public class ProgressBar extends View {
private static final int MAX_LEVEL = 10000;
- private static final int TIMEOUT_SEND_ACCESSIBILITY_EVENT = 200;
/** Interpolator used for smooth progress animations. */
private static final DecelerateInterpolator PROGRESS_ANIM_INTERPOLATOR =
@@ -244,8 +243,6 @@
private final ArrayList<RefreshData> mRefreshData = new ArrayList<RefreshData>();
- private AccessibilityEventSender mAccessibilityEventSender;
-
/**
* Create a new progress bar with range 0...100 and initial progress of 0.
* @param context the application environment
@@ -1556,7 +1553,7 @@
void onProgressRefresh(float scale, boolean fromUser, int progress) {
if (AccessibilityManager.getInstance(mContext).isEnabled()) {
- scheduleAccessibilityEventSender();
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
}
}
@@ -2250,9 +2247,6 @@
removeCallbacks(mRefreshProgressRunnable);
mRefreshIsPosted = false;
}
- if (mAccessibilityEventSender != null) {
- removeCallbacks(mAccessibilityEventSender);
- }
// This should come after stopAnimation(), otherwise an invalidate message remains in the
// queue, which can prevent the entire view hierarchy from being GC'ed during a rotation
super.onDetachedFromWindow();
@@ -2285,22 +2279,6 @@
}
}
- /**
- * Schedule a command for sending an accessibility event.
- * </br>
- * Note: A command is used to ensure that accessibility events
- * are sent at most one in a given time frame to save
- * system resources while the progress changes quickly.
- */
- private void scheduleAccessibilityEventSender() {
- if (mAccessibilityEventSender == null) {
- mAccessibilityEventSender = new AccessibilityEventSender();
- } else {
- removeCallbacks(mAccessibilityEventSender);
- }
- postDelayed(mAccessibilityEventSender, TIMEOUT_SEND_ACCESSIBILITY_EVENT);
- }
-
/** @hide */
@Override
protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
@@ -2324,15 +2302,6 @@
return isIndeterminate() && getWindowVisibility() == VISIBLE && isShown();
}
- /**
- * Command for sending an accessibility event.
- */
- private class AccessibilityEventSender implements Runnable {
- public void run() {
- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
- }
- }
-
private static class ProgressTintInfo {
ColorStateList mIndeterminateTintList;
BlendMode mIndeterminateBlendMode;
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 6b324a5..167010b8 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -73,7 +73,7 @@
*
* <p>This behavior has been preserved for apps that set <code>android:targetSdkVersion="17"</code>
* or older in their manifest's <code>uses-sdk</code> tag for compatibility. Apps targeting SDK
- * version 18 or newer will receive the correct behavior</p>
+ * version 18 or newer will receive the correct behavior.</p>
*
* <p>See the <a href="{@docRoot}guide/topics/ui/layout/relative.html">Relative
* Layout</a> guide.</p>
diff --git a/core/java/android/widget/SimpleMonthView.java b/core/java/android/widget/SimpleMonthView.java
index 562cc4f..217693e 100644
--- a/core/java/android/widget/SimpleMonthView.java
+++ b/core/java/android/widget/SimpleMonthView.java
@@ -28,6 +28,7 @@
import android.graphics.Rect;
import android.graphics.Typeface;
import android.icu.text.DisplayContext;
+import android.icu.text.RelativeDateTimeFormatter;
import android.icu.text.SimpleDateFormat;
import android.icu.util.Calendar;
import android.os.Bundle;
@@ -1095,6 +1096,14 @@
node.setText(getDayText(virtualViewId));
node.setContentDescription(getDayDescription(virtualViewId));
+ if (virtualViewId == mToday) {
+ RelativeDateTimeFormatter fmt = RelativeDateTimeFormatter.getInstance();
+ node.setStateDescription(fmt.format(RelativeDateTimeFormatter.Direction.THIS,
+ RelativeDateTimeFormatter.AbsoluteUnit.DAY));
+ }
+ if (virtualViewId == mActivatedDay) {
+ node.setSelected(true);
+ }
node.setBoundsInParent(mTempRect);
final boolean isDayEnabled = isDayEnabled(virtualViewId);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 31f5055..90e8ef2 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -345,6 +345,8 @@
public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
static final String LOG_TAG = "TextView";
static final boolean DEBUG_EXTRACT = false;
+ static final boolean DEBUG_CURSOR = false;
+
private static final float[] TEMP_POSITION = new float[2];
// Enum for the "typeface" XML parameter.
@@ -10857,6 +10859,10 @@
@Override
public boolean onTouchEvent(MotionEvent event) {
+ if (DEBUG_CURSOR) {
+ logCursor("onTouchEvent", MotionEvent.actionToString(event.getActionMasked()));
+ }
+
final int action = event.getActionMasked();
if (mEditor != null) {
mEditor.onTouchEvent(event);
@@ -10868,6 +10874,9 @@
}
final boolean superResult = super.onTouchEvent(event);
+ if (DEBUG_CURSOR) {
+ logCursor("onTouchEvent", "superResult=%s", superResult);
+ }
/*
* Don't handle the release after a long press, because it will move the selection away from
@@ -10876,7 +10885,9 @@
*/
if (mEditor != null && mEditor.mDiscardNextActionUp && action == MotionEvent.ACTION_UP) {
mEditor.mDiscardNextActionUp = false;
-
+ if (DEBUG_CURSOR) {
+ logCursor("onTouchEvent", "release after long press detected");
+ }
if (mEditor.mIsInsertionActionModeStartPending) {
mEditor.startInsertionActionMode();
mEditor.mIsInsertionActionModeStartPending = false;
@@ -12254,6 +12265,10 @@
@Override
public boolean performLongClick() {
+ if (DEBUG_CURSOR) {
+ logCursor("performLongClick", null);
+ }
+
boolean handled = false;
boolean performedHapticFeedback = false;
@@ -13481,4 +13496,12 @@
TextView.this.spanChange(buf, what, s, -1, e, -1);
}
}
+
+ private static void logCursor(String location, @Nullable String msgFormat, Object ... msgArgs) {
+ if (msgFormat == null) {
+ Log.d(LOG_TAG, location);
+ } else {
+ Log.d(LOG_TAG, location + ": " + String.format(msgFormat, msgArgs));
+ }
+ }
}
diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java
index 6eb470f..38f4c64 100644
--- a/core/java/com/android/internal/app/ChooserListAdapter.java
+++ b/core/java/com/android/internal/app/ChooserListAdapter.java
@@ -95,7 +95,7 @@
// we want to separate them into a different section.
super(context, payloadIntents, null, rList, filterLastUsed,
resolverListController, useLayoutForBrowsables,
- chooserListCommunicator);
+ chooserListCommunicator, false);
createPlaceHolders();
mMaxShortcutTargetsPerApp =
diff --git a/core/java/com/android/internal/app/DumpHeapActivity.java b/core/java/com/android/internal/app/DumpHeapActivity.java
deleted file mode 100644
index e04e870..0000000
--- a/core/java/com/android/internal/app/DumpHeapActivity.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.app;
-
-import android.app.Activity;
-import android.app.ActivityManager;
-import android.app.AlertDialog;
-import android.content.ActivityNotFoundException;
-import android.content.ClipData;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.util.DebugUtils;
-import android.util.Slog;
-
-/**
- * This activity is displayed when the system has collected a heap dump from
- * a large process and the user has selected to share it.
- */
-public class DumpHeapActivity extends Activity {
- /** The process we are reporting */
- public static final String KEY_PROCESS = "process";
- /** The size limit the process reached */
- public static final String KEY_SIZE = "size";
- /** Whether the user initiated the dump or not. */
- public static final String KEY_IS_USER_INITIATED = "is_user_initiated";
- /** Whether the process is a system process (eg: Android System) or not. */
- public static final String KEY_IS_SYSTEM_PROCESS = "is_system_process";
- /** Optional name of package to directly launch */
- public static final String KEY_DIRECT_LAUNCH = "direct_launch";
-
- // Broadcast action to determine when to delete the current dump heap data.
- public static final String ACTION_DELETE_DUMPHEAP = "com.android.server.am.DELETE_DUMPHEAP";
-
- // Extra for above: delay delete of data, since the user is in the process of sharing it.
- public static final String EXTRA_DELAY_DELETE = "delay_delete";
-
- static final public Uri JAVA_URI = Uri.parse("content://com.android.server.heapdump/java");
-
- String mProcess;
- long mSize;
- AlertDialog mDialog;
- boolean mHandled = false;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mProcess = getIntent().getStringExtra(KEY_PROCESS);
- mSize = getIntent().getLongExtra(KEY_SIZE, 0);
- final boolean isUserInitiated = getIntent().getBooleanExtra(KEY_IS_USER_INITIATED, false);
- final boolean isSystemProcess = getIntent().getBooleanExtra(KEY_IS_SYSTEM_PROCESS, false);
-
- String directLaunch = getIntent().getStringExtra(KEY_DIRECT_LAUNCH);
- if (directLaunch != null) {
- Intent intent = new Intent(ActivityManager.ACTION_REPORT_HEAP_LIMIT);
- intent.setPackage(directLaunch);
- ClipData clip = ClipData.newUri(getContentResolver(), "Heap Dump", JAVA_URI);
- intent.setClipData(clip);
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- intent.setType(clip.getDescription().getMimeType(0));
- intent.putExtra(Intent.EXTRA_STREAM, JAVA_URI);
- try {
- startActivity(intent);
- scheduleDelete();
- mHandled = true;
- finish();
- return;
- } catch (ActivityNotFoundException e) {
- Slog.i("DumpHeapActivity", "Unable to direct launch to " + directLaunch
- + ": " + e.getMessage());
- }
- }
-
- final int messageId;
- if (isUserInitiated) {
- messageId = com.android.internal.R.string.dump_heap_ready_text;
- } else if (isSystemProcess) {
- messageId = com.android.internal.R.string.dump_heap_system_text;
- } else {
- messageId = com.android.internal.R.string.dump_heap_text;
- }
- AlertDialog.Builder b = new AlertDialog.Builder(this,
- android.R.style.Theme_Material_Light_Dialog_Alert);
- b.setTitle(com.android.internal.R.string.dump_heap_title);
- b.setMessage(getString(
- messageId, mProcess, DebugUtils.sizeValueToString(mSize, null)));
- b.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- mHandled = true;
- sendBroadcast(new Intent(ACTION_DELETE_DUMPHEAP));
- finish();
- }
- });
- b.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- mHandled = true;
- scheduleDelete();
- Intent intent = new Intent(Intent.ACTION_SEND);
- ClipData clip = ClipData.newUri(getContentResolver(), "Heap Dump", JAVA_URI);
- intent.setClipData(clip);
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- intent.setType(clip.getDescription().getMimeType(0));
- intent.putExtra(Intent.EXTRA_STREAM, JAVA_URI);
- startActivity(Intent.createChooser(intent,
- getText(com.android.internal.R.string.dump_heap_title)));
- finish();
- }
- });
- mDialog = b.show();
- }
-
- void scheduleDelete() {
- Intent broadcast = new Intent(ACTION_DELETE_DUMPHEAP);
- broadcast.putExtra(EXTRA_DELAY_DELETE, true);
- sendBroadcast(broadcast);
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- if (!isChangingConfigurations()) {
- if (!mHandled) {
- sendBroadcast(new Intent(ACTION_DELETE_DUMPHEAP));
- }
- }
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mDialog.dismiss();
- }
-}
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 3ab0b0d2..99bf93e 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -31,19 +31,19 @@
// be kept in sync with frameworks/native/libs/binder/include/binder/IAppOpsService.h
// and not be reordered
int checkOperation(int code, int uid, String packageName);
- int noteOperation(int code, int uid, String packageName, String featureId);
- int startOperation(IBinder token, int code, int uid, String packageName, String featureId,
- boolean startIfModeDefault);
+ int noteOperation(int code, int uid, String packageName, @nullable String featureId);
+ int startOperation(IBinder token, int code, int uid, String packageName,
+ @nullable String featureId, boolean startIfModeDefault);
@UnsupportedAppUsage
void finishOperation(IBinder token, int code, int uid, String packageName,
- String featureId);
+ @nullable String featureId);
void startWatchingMode(int op, String packageName, IAppOpsCallback callback);
void stopWatchingMode(IAppOpsCallback callback);
IBinder getToken(IBinder clientToken);
int permissionToOpCode(String permission);
int checkAudioOperation(int code, int usage, int uid, String packageName);
- void noteAsyncOp(String callingPackageName, int uid, String packageName, int opCode,
- String featureId, String message);
+ void noteAsyncOp(@nullable String callingPackageName, int uid, @nullable String packageName,
+ int opCode, @nullable String featureId, String message);
boolean shouldCollectNotes(int opCode);
void setCameraAudioRestriction(int mode);
// End of methods also called by native code.
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index c1c6ac9..1beb1c5 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -140,6 +140,9 @@
private final PackageMonitor mPackageMonitor = createPackageMonitor();
+ // Intent extra for connected audio devices
+ public static final String EXTRA_IS_AUDIO_CAPTURE_DEVICE = "is_audio_capture_device";
+
/**
* Get the string resource to be used as a label for the link to the resolver activity for an
* action.
@@ -1038,8 +1041,14 @@
public ResolverListAdapter createAdapter(Context context, List<Intent> payloadIntents,
Intent[] initialIntents, List<ResolveInfo> rList,
boolean filterLastUsed, boolean useLayoutForBrowsables) {
+
+ Intent startIntent = getIntent();
+ boolean isAudioCaptureDevice =
+ startIntent.getBooleanExtra(EXTRA_IS_AUDIO_CAPTURE_DEVICE, false);
+
return new ResolverListAdapter(context, payloadIntents, initialIntents, rList,
- filterLastUsed, createListController(), useLayoutForBrowsables, this);
+ filterLastUsed, createListController(), useLayoutForBrowsables, this,
+ isAudioCaptureDevice);
}
@VisibleForTesting
diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java
index 4076dda..0286aa6 100644
--- a/core/java/com/android/internal/app/ResolverListAdapter.java
+++ b/core/java/com/android/internal/app/ResolverListAdapter.java
@@ -24,6 +24,7 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.PermissionChecker;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.LabeledIntent;
@@ -86,13 +87,15 @@
private boolean mFilterLastUsed;
private final ResolverListCommunicator mResolverListCommunicator;
private Runnable mPostListReadyRunnable;
+ private final boolean mIsAudioCaptureDevice;
public ResolverListAdapter(Context context, List<Intent> payloadIntents,
Intent[] initialIntents, List<ResolveInfo> rList,
boolean filterLastUsed,
ResolverListController resolverListController,
boolean useLayoutForBrowsables,
- ResolverListCommunicator resolverListCommunicator) {
+ ResolverListCommunicator resolverListCommunicator,
+ boolean isAudioCaptureDevice) {
mContext = context;
mIntents = payloadIntents;
mInitialIntents = initialIntents;
@@ -105,6 +108,7 @@
mSuspendedMatrixColorFilter = createSuspendedColorMatrix();
mUseLayoutForBrowsables = useLayoutForBrowsables;
mResolverListCommunicator = resolverListCommunicator;
+ mIsAudioCaptureDevice = isAudioCaptureDevice;
final ActivityManager am = (ActivityManager) mContext.getSystemService(ACTIVITY_SERVICE);
mIconDpi = am.getLauncherLargeIconDensity();
}
@@ -630,8 +634,7 @@
subLabel = null;
}
- if (!TextUtils.equals(text2.getText(), subLabel)
- && !TextUtils.isEmpty(subLabel)) {
+ if (!TextUtils.equals(text2.getText(), subLabel)) {
text2.setVisibility(View.VISIBLE);
text2.setText(subLabel);
}
@@ -651,6 +654,29 @@
protected CharSequence[] doInBackground(Void... voids) {
ResolveInfoPresentationGetter pg =
makePresentationGetter(mDisplayResolveInfo.getResolveInfo());
+
+ if (mIsAudioCaptureDevice) {
+ // This is an audio capture device, so check record permissions
+ ActivityInfo activityInfo = mDisplayResolveInfo.getResolveInfo().activityInfo;
+ String packageName = activityInfo.packageName;
+
+ int uid = activityInfo.applicationInfo.uid;
+ boolean hasRecordPermission =
+ PermissionChecker.checkPermissionForPreflight(
+ mContext,
+ android.Manifest.permission.RECORD_AUDIO, -1, uid,
+ packageName)
+ == android.content.pm.PackageManager.PERMISSION_GRANTED;
+
+ if (!hasRecordPermission) {
+ // Doesn't have record permission, so warn the user
+ return new CharSequence[] {
+ pg.getLabel(),
+ mContext.getString(R.string.usb_device_resolve_prompt_warn)
+ };
+ }
+ }
+
return new CharSequence[] {
pg.getLabel(),
pg.getSubLabel()
diff --git a/core/java/com/android/internal/app/procstats/ProcessState.java b/core/java/com/android/internal/app/procstats/ProcessState.java
index 2f9136a..392b8d3 100644
--- a/core/java/com/android/internal/app/procstats/ProcessState.java
+++ b/core/java/com/android/internal/app/procstats/ProcessState.java
@@ -77,7 +77,6 @@
STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
STATE_TOP, // ActivityManager.PROCESS_STATE_TOP
- STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION
STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_TOP
STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
STATE_IMPORTANT_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
diff --git a/core/java/com/android/internal/compat/CompatibilityChangeConfig.java b/core/java/com/android/internal/compat/CompatibilityChangeConfig.java
index fd2ada0..36bc229 100644
--- a/core/java/com/android/internal/compat/CompatibilityChangeConfig.java
+++ b/core/java/com/android/internal/compat/CompatibilityChangeConfig.java
@@ -49,6 +49,18 @@
return mChangeConfig.forceDisabledSet();
}
+ /**
+ * Returns if a change is enabled or disabled in this config.
+ */
+ public boolean isChangeEnabled(long changeId) {
+ if (mChangeConfig.isForceEnabled(changeId)) {
+ return true;
+ } else if (mChangeConfig.isForceDisabled(changeId)) {
+ return false;
+ }
+ throw new IllegalStateException("Change " + changeId + " is not defined.");
+ }
+
private CompatibilityChangeConfig(Parcel in) {
long[] enabledArray = in.createLongArray();
long[] disabledArray = in.createLongArray();
diff --git a/core/java/com/android/internal/compat/CompatibilityChangeInfo.aidl b/core/java/com/android/internal/compat/CompatibilityChangeInfo.aidl
new file mode 100644
index 0000000..3bc7277
--- /dev/null
+++ b/core/java/com/android/internal/compat/CompatibilityChangeInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.compat;
+
+parcelable CompatibilityChangeInfo;
diff --git a/core/java/com/android/internal/compat/CompatibilityChangeInfo.java b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java
new file mode 100644
index 0000000..e48e2df
--- /dev/null
+++ b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.compat;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class is a parcelable version of {@link com.android.server.compat.Change}.
+ *
+ * @hide
+ */
+public class CompatibilityChangeInfo implements Parcelable {
+ private final long mChangeId;
+ private final @Nullable String mName;
+ private final int mEnableAfterTargetSdk;
+ private final boolean mDisabled;
+
+ public long getId() {
+ return mChangeId;
+ }
+
+ @Nullable
+ public String getName() {
+ return mName;
+ }
+
+ public int getEnableAfterTargetSdk() {
+ return mEnableAfterTargetSdk;
+ }
+
+ public boolean getDisabled() {
+ return mDisabled;
+ }
+
+ public CompatibilityChangeInfo(
+ Long changeId, String name, int enableAfterTargetSdk, boolean disabled) {
+ this.mChangeId = changeId;
+ this.mName = name;
+ this.mEnableAfterTargetSdk = enableAfterTargetSdk;
+ this.mDisabled = disabled;
+ }
+
+ private CompatibilityChangeInfo(Parcel in) {
+ mChangeId = in.readLong();
+ mName = in.readString();
+ mEnableAfterTargetSdk = in.readInt();
+ mDisabled = in.readBoolean();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(mChangeId);
+ dest.writeString(mName);
+ dest.writeInt(mEnableAfterTargetSdk);
+ dest.writeBoolean(mDisabled);
+ }
+
+ public static final Parcelable.Creator<CompatibilityChangeInfo> CREATOR =
+ new Parcelable.Creator<CompatibilityChangeInfo>() {
+
+ @Override
+ public CompatibilityChangeInfo createFromParcel(Parcel in) {
+ return new CompatibilityChangeInfo(in);
+ }
+
+ @Override
+ public CompatibilityChangeInfo[] newArray(int size) {
+ return new CompatibilityChangeInfo[size];
+ }
+ };
+}
diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl
index 8391ad2..5857642 100644
--- a/core/java/com/android/internal/compat/IPlatformCompat.aidl
+++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl
@@ -17,8 +17,10 @@
package com.android.internal.compat;
import android.content.pm.ApplicationInfo;
+import java.util.Map;
parcelable CompatibilityChangeConfig;
+parcelable CompatibilityChangeInfo;
/**
* Platform private API for talking with the PlatformCompat service.
@@ -146,4 +148,21 @@
*
*/
void clearOverrides(in String packageName);
+
+ /**
+ * Get configs for an application.
+ *
+ * @param appInfo The application whose config will be returned.
+ *
+ * @return A {@link CompatibilityChangeConfig}, representing whether a change is enabled for
+ * the given app or not.
+ */
+ CompatibilityChangeConfig getAppConfig(in ApplicationInfo appInfo);
+
+ /**
+ * List all compatibility changes.
+ *
+ * @return An array of {@link CompatChangeInfo} known to the service.
+ */
+ CompatibilityChangeInfo[] listAllChanges();
}
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 033e9b2..58e80c7 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -47,6 +47,20 @@
*/
public static final String NAS_MAX_SUGGESTIONS = "nas_max_suggestions";
+ // Flags related to screenshot intelligence
+
+ /**
+ * (bool) Whether to enable smart actions in screenshot notifications.
+ */
+ public static final String ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS =
+ "enable_screenshot_notification_smart_actions";
+
+ /**
+ * (int) Timeout value in ms to get smart actions for screenshot notification.
+ */
+ public static final String SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS =
+ "screenshot_notification_smart_actions_timeout_ms";
+
// Flags related to controls
/**
@@ -337,6 +351,14 @@
"brightline_falsing_zigzag_y_secondary_deviance";
+ // Flags related to screenshots
+
+ /**
+ * (boolean) Whether screenshot flow going to the corner (instead of shown in a notification)
+ * is enabled.
+ */
+ public static final String SCREENSHOT_CORNER_FLOW = "screenshot_corner_flow";
+
private SystemUiDeviceConfigFlags() {
}
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodDebug.java b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
index 025e27b..382a254b 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodDebug.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
@@ -168,9 +168,6 @@
if ((startInputFlags & StartInputFlags.IS_TEXT_EDITOR) != 0) {
joiner.add("IS_TEXT_EDITOR");
}
- if ((startInputFlags & StartInputFlags.FIRST_WINDOW_FOCUS_GAIN) != 0) {
- joiner.add("FIRST_WINDOW_FOCUS_GAIN");
- }
if ((startInputFlags & StartInputFlags.INITIAL_CONNECTION) != 0) {
joiner.add("INITIAL_CONNECTION");
}
diff --git a/core/java/com/android/internal/inputmethod/StartInputFlags.java b/core/java/com/android/internal/inputmethod/StartInputFlags.java
index ba26d8d..5a8d2c2 100644
--- a/core/java/com/android/internal/inputmethod/StartInputFlags.java
+++ b/core/java/com/android/internal/inputmethod/StartInputFlags.java
@@ -30,7 +30,6 @@
@IntDef(flag = true, value = {
StartInputFlags.VIEW_HAS_FOCUS,
StartInputFlags.IS_TEXT_EDITOR,
- StartInputFlags.FIRST_WINDOW_FOCUS_GAIN,
StartInputFlags.INITIAL_CONNECTION})
public @interface StartInputFlags {
/**
@@ -44,13 +43,8 @@
int IS_TEXT_EDITOR = 2;
/**
- * This is the first time the window has gotten focus.
- */
- int FIRST_WINDOW_FOCUS_GAIN = 4;
-
- /**
* An internal concept to distinguish "start" and "restart". This concept doesn't look well
* documented hence we probably need to revisit this though.
*/
- int INITIAL_CONNECTION = 8;
+ int INITIAL_CONNECTION = 4;
}
diff --git a/core/java/com/android/internal/os/BaseCommand.java b/core/java/com/android/internal/os/BaseCommand.java
index 278f406..e1b8e6c 100644
--- a/core/java/com/android/internal/os/BaseCommand.java
+++ b/core/java/com/android/internal/os/BaseCommand.java
@@ -18,14 +18,14 @@
package com.android.internal.os;
import android.annotation.UnsupportedAppUsage;
-import android.os.ShellCommand;
+import android.os.BasicShellCommandHandler;
import java.io.PrintStream;
public abstract class BaseCommand {
@UnsupportedAppUsage
- final protected ShellCommand mArgs = new ShellCommand() {
+ final protected BasicShellCommandHandler mArgs = new BasicShellCommandHandler() {
@Override public int onCommand(String cmd) {
return 0;
}
@@ -50,7 +50,7 @@
}
mRawArgs = args;
- mArgs.init(null, null, null, null, args, null, 0);
+ mArgs.init(null, null, null, null, args, 0);
try {
onRun();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index d6b32b5..f5bfe5c 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -12618,20 +12618,20 @@
txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
totalTxTimeMs += txTimeMs[i];
}
- s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
- s.setKernelActiveTimeMs(getMobileRadioActiveTime(rawRealTime, which) / 1000);
+ s.setLoggingDurationMillis(computeBatteryRealtime(rawRealTime, which) / 1000);
+ s.setKernelActiveTimeMillis(getMobileRadioActiveTime(rawRealTime, which) / 1000);
s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which));
s.setNumBytesTx(getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which));
s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which));
s.setNumBytesRx(getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which));
- s.setSleepTimeMs(sleepTimeMs);
- s.setIdleTimeMs(idleTimeMs);
- s.setRxTimeMs(rxTimeMs);
- s.setEnergyConsumedMaMs(energyConsumedMaMs);
- s.setTimeInRatMs(timeInRatMs);
- s.setTimeInRxSignalStrengthLevelMs(timeInRxSignalStrengthLevelMs);
- s.setTxTimeMs(txTimeMs);
- s.setMonitoredRailChargeConsumedMaMs(monitoredRailChargeConsumedMaMs);
+ s.setSleepTimeMillis(sleepTimeMs);
+ s.setIdleTimeMillis(idleTimeMs);
+ s.setRxTimeMillis(rxTimeMs);
+ s.setEnergyConsumedMaMillis(energyConsumedMaMs);
+ s.setTimeInRatMicros(timeInRatMs);
+ s.setTimeInRxSignalStrengthLevelMicros(timeInRxSignalStrengthLevelMs);
+ s.setTxTimeMillis(txTimeMs);
+ s.setMonitoredRailChargeConsumedMaMillis(monitoredRailChargeConsumedMaMs);
return s;
}
diff --git a/core/java/com/android/internal/os/KernelCpuUidTimeReader.java b/core/java/com/android/internal/os/KernelCpuUidTimeReader.java
index e6d044f..f1eb2fb 100644
--- a/core/java/com/android/internal/os/KernelCpuUidTimeReader.java
+++ b/core/java/com/android/internal/os/KernelCpuUidTimeReader.java
@@ -403,7 +403,7 @@
}
private long[] readFreqs(String line) {
- if (line == null) {
+ if (line == null || line.trim().isEmpty()) {
return null;
}
final String[] lineArray = line.split(" ");
@@ -620,14 +620,18 @@
return true;
}
- String str = line.toString();
+ String str = line.toString().trim();
+ if (str.isEmpty()) {
+ Slog.w(mTag, "Empty uid_concurrent_active_time");
+ return false;
+ }
if (!str.startsWith("cpus:")) {
- Slog.wtf(mTag, "Malformed uid_concurrent_active_time line: " + line);
+ Slog.wtf(mTag, "Malformed uid_concurrent_active_time line: " + str);
return false;
}
int cores = Integer.parseInt(str.substring(5).trim(), 10);
if (cores <= 0) {
- Slog.wtf(mTag, "Malformed uid_concurrent_active_time line: " + line);
+ Slog.wtf(mTag, "Malformed uid_concurrent_active_time line: " + str);
return false;
}
mCores = cores;
@@ -750,17 +754,22 @@
if (mNumClusters > 0) {
return true;
}
+ String lineStr = line.toString().trim();
+ if (lineStr.isEmpty()) {
+ Slog.w(mTag, "Empty uid_concurrent_policy_time");
+ return false;
+ }
// Parse # cores in clusters.
- String[] lineArray = line.toString().split(" ");
+ String[] lineArray = lineStr.split(" ");
if (lineArray.length % 2 != 0) {
- Slog.wtf(mTag, "Malformed uid_concurrent_policy_time line: " + line);
+ Slog.wtf(mTag, "Malformed uid_concurrent_policy_time line: " + lineStr);
return false;
}
int[] clusters = new int[lineArray.length / 2];
int cores = 0;
for (int i = 0; i < clusters.length; i++) {
if (!lineArray[i * 2].startsWith("policy")) {
- Slog.wtf(mTag, "Malformed uid_concurrent_policy_time line: " + line);
+ Slog.wtf(mTag, "Malformed uid_concurrent_policy_time line: " + lineStr);
return false;
}
clusters[i] = Integer.parseInt(lineArray[i * 2 + 1], 10);
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 3ce3838..f3de34b 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -114,6 +114,13 @@
*/
public static final int DEBUG_IGNORE_APP_SIGNAL_HANDLER = 1 << 17;
+ /**
+ * Disable runtime access to {@link android.annotation.TestApi} annotated members.
+ *
+ * <p>This only takes effect if Hidden API access restrictions are enabled as well.
+ */
+ public static final int DISABLE_TEST_API_ENFORCEMENT_POLICY = 1 << 18;
+
/** No external storage should be mounted. */
public static final int MOUNT_EXTERNAL_NONE = IVold.REMOUNT_MODE_NONE;
/** Default external storage should be mounted. */
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 317469e..73f549a 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -38,25 +38,6 @@
void showWirelessChargingAnimation(int batteryLevel);
- /**
- * Notifies System UI side of a visibility flag change on the specified display.
- *
- * @param displayId the id of the display to notify
- * @param vis the visibility flags except SYSTEM_UI_FLAG_LIGHT_STATUS_BAR which will be reported
- * separately in fullscreenStackVis and dockedStackVis
- * @param fullscreenStackVis the flags which only apply in the region of the fullscreen stack,
- * which is currently only SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
- * @param dockedStackVis the flags that only apply in the region of the docked stack, which is
- * currently only SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
- * @param mask which flags to change
- * @param fullscreenBounds the current bounds of the fullscreen stack, in screen coordinates
- * @param dockedBounds the current bounds of the docked stack, in screen coordinates
- * @param navbarColorManagedByIme {@code true} if navigation bar color is managed by IME.
- */
- void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, int dockedStackVis,
- int mask, in Rect fullscreenBounds, in Rect dockedBounds,
- boolean navbarColorManagedByIme);
-
void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive);
void setImeWindowStatus(int displayId, in IBinder token, int vis, int backDisposition,
boolean showImeSwitcher, boolean isMultiClientImeEnabled);
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 499a4d2..3f08710 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -21,6 +21,7 @@
import android.content.ComponentName;
import android.graphics.Rect;
import android.os.Bundle;
+import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.hardware.biometrics.IBiometricServiceReceiverInternal;
@@ -76,9 +77,9 @@
void onNotificationSmartReplySent(in String key, in int replyIndex, in CharSequence reply,
in int notificationLocation, boolean modifiedBeforeSending);
void onNotificationSettingsViewed(String key);
- void setSystemUiVisibility(int displayId, int vis, int mask, String cause);
void onNotificationBubbleChanged(String key, boolean isBubble);
- void grantInlineReplyUriPermission(String key, in Uri uri);
+ void grantInlineReplyUriPermission(String key, in Uri uri, in UserHandle user, String packageName);
+ void clearInlineReplyUriPermissions(String key);
void onGlobalActionsShown();
void onGlobalActionsHidden();
diff --git a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
index 4c3f04b..9095f05 100644
--- a/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
+++ b/core/java/com/android/internal/statusbar/RegisterStatusBarResult.java
@@ -16,53 +16,50 @@
package com.android.internal.statusbar;
-import android.graphics.Rect;
+import android.annotation.NonNull;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
+import com.android.internal.view.AppearanceRegion;
+
/**
* An immutable data object to return a set of values from StatusBarManagerService to its clients.
*/
public final class RegisterStatusBarResult implements Parcelable {
public final ArrayMap<String, StatusBarIcon> mIcons;
- public final int mDisabledFlags1; // switch[0]
- public final int mSystemUiVisibility; // switch[1]
- public final int mImeWindowVis; // switch[3]
- public final int mImeBackDisposition; // switch[4]
- public final boolean mShowImeSwitcher; // switch[5]
- public final int mDisabledFlags2; // switch[6]
- public final int mFullscreenStackSysUiVisibility; // switch[7]
- public final int mDockedStackSysUiVisibility; // switch[8]
+ public final int mDisabledFlags1; // switch[0]
+ public final int mAppearance; // switch[1]
+ public final AppearanceRegion[] mAppearanceRegions; // switch[2]
+ public final int mImeWindowVis; // switch[3]
+ public final int mImeBackDisposition; // switch[4]
+ public final boolean mShowImeSwitcher; // switch[5]
+ public final int mDisabledFlags2; // switch[6]
public final IBinder mImeToken;
- public final Rect mFullscreenStackBounds;
- public final Rect mDockedStackBounds;
public final boolean mNavbarColorManagedByIme;
public final boolean mAppFullscreen;
public final boolean mAppImmersive;
+ public final int[] mTransientBarTypes;
public RegisterStatusBarResult(ArrayMap<String, StatusBarIcon> icons, int disabledFlags1,
- int systemUiVisibility, int imeWindowVis, int imeBackDisposition,
- boolean showImeSwitcher, int disabledFlags2, int fullscreenStackSysUiVisibility,
- int dockedStackSysUiVisibility, IBinder imeToken, Rect fullscreenStackBounds,
- Rect dockedStackBounds, boolean navbarColorManagedByIme, boolean appFullscreen,
- boolean appImmersive) {
+ int appearance, AppearanceRegion[] appearanceRegions, int imeWindowVis,
+ int imeBackDisposition, boolean showImeSwitcher, int disabledFlags2, IBinder imeToken,
+ boolean navbarColorManagedByIme, boolean appFullscreen, boolean appImmersive,
+ @NonNull int[] transientBarTypes) {
mIcons = new ArrayMap<>(icons);
mDisabledFlags1 = disabledFlags1;
- mSystemUiVisibility = systemUiVisibility;
+ mAppearance = appearance;
+ mAppearanceRegions = appearanceRegions;
mImeWindowVis = imeWindowVis;
mImeBackDisposition = imeBackDisposition;
mShowImeSwitcher = showImeSwitcher;
mDisabledFlags2 = disabledFlags2;
- mFullscreenStackSysUiVisibility = fullscreenStackSysUiVisibility;
- mDockedStackSysUiVisibility = dockedStackSysUiVisibility;
mImeToken = imeToken;
- mFullscreenStackBounds = fullscreenStackBounds;
- mDockedStackBounds = dockedStackBounds;
mNavbarColorManagedByIme = navbarColorManagedByIme;
mAppFullscreen = appFullscreen;
mAppImmersive = appImmersive;
+ mTransientBarTypes = transientBarTypes;
}
@Override
@@ -74,19 +71,17 @@
public void writeToParcel(Parcel dest, int flags) {
dest.writeTypedArrayMap(mIcons, flags);
dest.writeInt(mDisabledFlags1);
- dest.writeInt(mSystemUiVisibility);
+ dest.writeInt(mAppearance);
+ dest.writeParcelableArray(mAppearanceRegions, 0);
dest.writeInt(mImeWindowVis);
dest.writeInt(mImeBackDisposition);
dest.writeBoolean(mShowImeSwitcher);
dest.writeInt(mDisabledFlags2);
- dest.writeInt(mFullscreenStackSysUiVisibility);
- dest.writeInt(mDockedStackSysUiVisibility);
dest.writeStrongBinder(mImeToken);
- dest.writeTypedObject(mFullscreenStackBounds, flags);
- dest.writeTypedObject(mDockedStackBounds, flags);
dest.writeBoolean(mNavbarColorManagedByIme);
dest.writeBoolean(mAppFullscreen);
dest.writeBoolean(mAppImmersive);
+ dest.writeIntArray(mTransientBarTypes);
}
/**
@@ -99,24 +94,22 @@
final ArrayMap<String, StatusBarIcon> icons =
source.createTypedArrayMap(StatusBarIcon.CREATOR);
final int disabledFlags1 = source.readInt();
- final int systemUiVisibility = source.readInt();
+ final int appearance = source.readInt();
+ final AppearanceRegion[] appearanceRegions =
+ source.readParcelableArray(null, AppearanceRegion.class);
final int imeWindowVis = source.readInt();
final int imeBackDisposition = source.readInt();
final boolean showImeSwitcher = source.readBoolean();
final int disabledFlags2 = source.readInt();
- final int fullscreenStackSysUiVisibility = source.readInt();
- final int dockedStackSysUiVisibility = source.readInt();
final IBinder imeToken = source.readStrongBinder();
- final Rect fullscreenStackBounds = source.readTypedObject(Rect.CREATOR);
- final Rect dockedStackBounds = source.readTypedObject(Rect.CREATOR);
final boolean navbarColorManagedByIme = source.readBoolean();
final boolean appFullscreen = source.readBoolean();
final boolean appImmersive = source.readBoolean();
- return new RegisterStatusBarResult(icons, disabledFlags1, systemUiVisibility,
- imeWindowVis, imeBackDisposition, showImeSwitcher, disabledFlags2,
- fullscreenStackSysUiVisibility, dockedStackSysUiVisibility, imeToken,
- fullscreenStackBounds, dockedStackBounds, navbarColorManagedByIme,
- appFullscreen, appImmersive);
+ final int[] transientBarTypes = source.createIntArray();
+ return new RegisterStatusBarResult(icons, disabledFlags1, appearance,
+ appearanceRegions, imeWindowVis, imeBackDisposition, showImeSwitcher,
+ disabledFlags2, imeToken, navbarColorManagedByIme, appFullscreen,
+ appImmersive, transientBarTypes);
}
@Override
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index b752396..ed7f5de 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -540,6 +540,7 @@
Slog.w(TAG, "Couldn't find or open permissions file " + permFile);
return;
}
+ Slog.i(TAG, "Reading permissions from " + permFile);
final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
@@ -863,11 +864,7 @@
XmlUtils.skipCurrentTag(parser);
} break;
case "component-override": {
- if (allowAppConfigs) {
- readComponentOverrides(parser, permFile);
- } else {
- logNotAllowedInPartition(name, permFile, parser);
- }
+ readComponentOverrides(parser, permFile);
XmlUtils.skipCurrentTag(parser);
} break;
case "backup-transport-whitelisted-service": {
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index d9428c5..8d71237 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -246,6 +246,7 @@
"libmediametrics",
"libmeminfo",
"libaudioclient",
+ "libaudiofoundation",
"libaudiopolicy",
"libusbhost",
"libpdfium",
diff --git a/core/jni/android_graphics_Picture.cpp b/core/jni/android_graphics_Picture.cpp
index 03fcdef..1d085e5 100644
--- a/core/jni/android_graphics_Picture.cpp
+++ b/core/jni/android_graphics_Picture.cpp
@@ -20,9 +20,12 @@
#include "SkCanvas.h"
#include "SkStream.h"
#include "core_jni_helpers.h"
+#include "nativehelper/jni_macros.h"
#include <jni.h>
+#include <array>
+
namespace android {
static jlong android_graphics_Picture_newPicture(JNIEnv* env, jobject, jlong srcHandle) {
@@ -91,20 +94,20 @@
pict->endRecording();
}
-static const JNINativeMethod gMethods[] = {
- {"nativeGetWidth", "(J)I", (void*) android_graphics_Picture_getWidth},
- {"nativeGetHeight", "(J)I", (void*) android_graphics_Picture_getHeight},
- {"nativeConstructor", "(J)J", (void*) android_graphics_Picture_newPicture},
- {"nativeCreateFromStream", "(Ljava/io/InputStream;[B)J", (void*)android_graphics_Picture_deserialize},
- {"nativeBeginRecording", "(JII)J", (void*) android_graphics_Picture_beginRecording},
- {"nativeEndRecording", "(J)V", (void*) android_graphics_Picture_endRecording},
- {"nativeDraw", "(JJ)V", (void*) android_graphics_Picture_draw},
- {"nativeWriteToStream", "(JLjava/io/OutputStream;[B)Z", (void*)android_graphics_Picture_serialize},
- {"nativeDestructor","(J)V", (void*) android_graphics_Picture_killPicture}
+static const std::array gMethods = {
+ MAKE_JNI_NATIVE_METHOD("nativeGetWidth", "(J)I", android_graphics_Picture_getWidth),
+ MAKE_JNI_NATIVE_METHOD("nativeGetHeight", "(J)I", android_graphics_Picture_getHeight),
+ MAKE_JNI_NATIVE_METHOD("nativeConstructor", "(J)J", android_graphics_Picture_newPicture),
+ MAKE_JNI_NATIVE_METHOD("nativeCreateFromStream", "(Ljava/io/InputStream;[B)J", android_graphics_Picture_deserialize),
+ MAKE_JNI_NATIVE_METHOD("nativeBeginRecording", "(JII)J", android_graphics_Picture_beginRecording),
+ MAKE_JNI_NATIVE_METHOD("nativeEndRecording", "(J)V", android_graphics_Picture_endRecording),
+ MAKE_JNI_NATIVE_METHOD("nativeDraw", "(JJ)V", android_graphics_Picture_draw),
+ MAKE_JNI_NATIVE_METHOD("nativeWriteToStream", "(JLjava/io/OutputStream;[B)Z", android_graphics_Picture_serialize),
+ MAKE_JNI_NATIVE_METHOD("nativeDestructor","(J)V", android_graphics_Picture_killPicture)
};
int register_android_graphics_Picture(JNIEnv* env) {
- return RegisterMethodsOrDie(env, "android/graphics/Picture", gMethods, NELEM(gMethods));
+ return RegisterMethodsOrDie(env, "android/graphics/Picture", gMethods.data(), gMethods.size());
}
}; // namespace android
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 686a919..6417b28 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -27,6 +27,7 @@
#include "core_jni_helpers.h"
#include <audiomanager/AudioManager.h>
+#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioSystem.h>
#include <media/AudioPolicy.h>
#include <media/MicrophoneInfo.h>
@@ -2015,9 +2016,10 @@
if (!env->IsInstanceOf(addrJobj, stringClass)) {
return (jint) AUDIO_JAVA_BAD_VALUE;
}
- String8 address = String8(env->GetStringUTFChars((jstring) addrJobj, NULL));
+ const char* address = env->GetStringUTFChars((jstring) addrJobj, NULL);
AudioDeviceTypeAddr dev = AudioDeviceTypeAddr(typesPtr[i], address);
deviceVector.add(dev);
+ env->ReleaseStringUTFChars((jstring) addrJobj, address);
}
env->ReleaseIntArrayElements(deviceTypes, typesPtr, 0);
diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp
index bf1cea8..891520a 100644
--- a/core/jni/android_view_InputChannel.cpp
+++ b/core/jni/android_view_InputChannel.cpp
@@ -276,20 +276,12 @@
NativeInputChannel* nativeInputChannel =
android_view_InputChannel_getNativeInputChannel(env, obj);
if (nativeInputChannel) {
- return javaObjectForIBinder(env, nativeInputChannel->getInputChannel()->getToken());
+ return javaObjectForIBinder(env,
+ nativeInputChannel->getInputChannel()->getConnectionToken());
}
return 0;
}
-static void android_view_InputChannel_nativeSetToken(JNIEnv* env, jobject obj, jobject tokenObj) {
- NativeInputChannel* nativeInputChannel =
- android_view_InputChannel_getNativeInputChannel(env, obj);
- sp<IBinder> token = ibinderForJavaObject(env, tokenObj);
- if (nativeInputChannel != nullptr) {
- nativeInputChannel->getInputChannel()->setToken(token);
- }
-}
-
// ----------------------------------------------------------------------------
static const JNINativeMethod gInputChannelMethods[] = {
@@ -312,8 +304,6 @@
(void*)android_view_InputChannel_nativeDup },
{ "nativeGetToken", "()Landroid/os/IBinder;",
(void*)android_view_InputChannel_nativeGetToken },
- { "nativeSetToken", "(Landroid/os/IBinder;)V",
- (void*)android_view_InputChannel_nativeSetToken }
};
int register_android_view_InputChannel(JNIEnv* env) {
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index c0e4e1f..3704ccd 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -59,8 +59,8 @@
return instance_;
}
-static bool IsMemfd(const std::string& path) {
- return android::base::StartsWith(path, "/memfd:");
+static bool IsArtMemfd(const std::string& path) {
+ return android::base::StartsWith(path, "/memfd:/boot-image-methods.art");
}
bool FileDescriptorWhitelist::IsAllowed(const std::string& path) const {
@@ -91,8 +91,8 @@
return true;
}
- // In-memory files created through memfd_create are allowed.
- if (IsMemfd(path)) {
+ // the in-memory file created by ART through memfd_create is allowed.
+ if (IsArtMemfd(path)) {
return true;
}
@@ -321,8 +321,8 @@
return DetachSocket(fail_fn);
}
- // Children can directly use in-memory files created through memfd_create.
- if (IsMemfd(file_path)) {
+ // Children can directly use the in-memory file created by ART through memfd_create.
+ if (IsArtMemfd(file_path)) {
return;
}
@@ -545,6 +545,10 @@
}
void FileDescriptorTable::RestatInternal(std::set<int>& open_fds, fail_fn_t fail_fn) {
+ // ART creates a file through memfd for optimization purposes. We make sure
+ // there is at most one being created.
+ bool art_memfd_seen = false;
+
// Iterate through the list of file descriptors we've already recorded
// and check whether :
//
@@ -577,6 +581,14 @@
// FD.
}
+ if (IsArtMemfd(it->second->file_path)) {
+ if (art_memfd_seen) {
+ fail_fn("ART fd already seen: " + it->second->file_path);
+ } else {
+ art_memfd_seen = true;
+ }
+ }
+
++it;
// Finally, remove the FD from the set of open_fds. We do this last because
diff --git a/core/proto/OWNERS b/core/proto/OWNERS
index 6ab0fc9..74ced89 100644
--- a/core/proto/OWNERS
+++ b/core/proto/OWNERS
@@ -3,8 +3,10 @@
# Metrics
joeo@google.com
singhtejinder@google.com
+yanmin@google.com
yaochen@google.com
yro@google.com
+zhouwenjie@google.com
# Settings UI
per-file settings_enums.proto=tmfang@google.com
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 7d0629ee..898e2f0 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -42,6 +42,7 @@
import "frameworks/base/core/proto/android/service/battery.proto";
import "frameworks/base/core/proto/android/service/batterystats.proto";
import "frameworks/base/core/proto/android/service/diskstats.proto";
+import "frameworks/base/core/proto/android/service/dropbox.proto";
import "frameworks/base/core/proto/android/service/graphicsstats.proto";
import "frameworks/base/core/proto/android/service/netstats.proto";
import "frameworks/base/core/proto/android/service/notification.proto";
@@ -87,42 +88,80 @@
optional android.util.LogProto main_logs = 1101 [
(section).type = SECTION_LOG,
- (section).args = "LOG_ID_MAIN"
+ (section).args = "main"
];
optional android.util.LogProto radio_logs = 1102 [
(section).type = SECTION_LOG,
- (section).args = "LOG_ID_RADIO"
+ (section).args = "radio"
];
optional android.util.LogProto events_logs = 1103 [
(section).type = SECTION_LOG,
- (section).args = "LOG_ID_EVENTS"
+ (section).args = "events"
];
optional android.util.LogProto system_logs = 1104 [
(section).type = SECTION_LOG,
- (section).args = "LOG_ID_SYSTEM"
+ (section).args = "system"
];
optional android.util.LogProto crash_logs = 1105 [
(section).type = SECTION_LOG,
- (section).args = "LOG_ID_CRASH"
+ (section).args = "crash"
];
optional android.util.LogProto stats_logs = 1106 [
(section).type = SECTION_LOG,
- (section).args = "LOG_ID_STATS"
+ (section).args = "stats"
];
optional android.util.LogProto security_logs = 1107 [
(section).type = SECTION_LOG,
- (section).args = "LOG_ID_SECURITY"
+ (section).args = "security"
];
optional android.util.LogProto kernel_logs = 1108 [
(section).type = SECTION_LOG,
- (section).args = "LOG_ID_KERNEL"
+ (section).args = "kernel"
+ ];
+
+ // Last logcat sections.
+ // Note that kernel logs is not persisted since it's contained in last kmsg.
+ optional android.util.LogProto last_main_logs = 1109 [
+ (section).type = SECTION_LOG,
+ (section).args = "main -L"
+ ];
+
+ optional android.util.LogProto last_radio_logs = 1110 [
+ (section).type = SECTION_LOG,
+ (section).args = "radio -L"
+ ];
+
+ optional android.util.LogProto last_events_logs = 1111 [
+ (section).type = SECTION_LOG,
+ (section).args = "events -L"
+ ];
+
+ optional android.util.LogProto last_system_logs = 1112 [
+ (section).type = SECTION_LOG,
+ (section).args = "system -L"
+ ];
+
+ optional android.util.LogProto last_crash_logs = 1113 [
+ (section).type = SECTION_LOG,
+ (section).args = "crash -L"
+ ];
+
+ optional android.util.LogProto last_stats_logs = 1114 [
+ (section).type = SECTION_LOG,
+ (section).args = "stats -L"
+ ];
+
+ // security logs is only available with "Device Owner" mode
+ optional android.util.LogProto last_security_logs = 1115 [
+ (section).type = SECTION_LOG,
+ (section).args = "security -L"
];
// Stack dumps
@@ -329,6 +368,22 @@
(section).userdebug_and_eng_only = true
];
+ // Dropbox entries split by tags.
+ optional android.service.dropbox.DropBoxManagerServiceDumpProto dropbox_data_app_crashes = 3027 [
+ (section).type = SECTION_DUMPSYS,
+ (section).args = "dropbox --proto data_app_crash"
+ ];
+
+ optional android.service.dropbox.DropBoxManagerServiceDumpProto dropbox_data_app_anr = 3028 [
+ (section).type = SECTION_DUMPSYS,
+ (section).args = "dropbox --proto data_app_anr"
+ ];
+
+ optional android.service.dropbox.DropBoxManagerServiceDumpProto dropbox_data_app_native_crash = 3029 [
+ (section).type = SECTION_DUMPSYS,
+ (section).args = "dropbox --proto data_app_native_crash"
+ ];
+
// Reserved for OEMs.
extensions 50000 to 100000;
}
diff --git a/core/proto/android/server/activitymanagerservice.proto b/core/proto/android/server/activitymanagerservice.proto
index d01a45c..b9d28e4 100644
--- a/core/proto/android/server/activitymanagerservice.proto
+++ b/core/proto/android/server/activitymanagerservice.proto
@@ -100,7 +100,8 @@
message TaskRecordProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
- optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1;
+ // To be removed soon.
+ optional .com.android.server.wm.ConfigurationContainerProto configuration_container = 1 [deprecated=true];
optional int32 id = 2;
repeated ActivityRecordProto activities = 3;
optional int32 stack_id = 4;
@@ -113,6 +114,7 @@
optional .android.graphics.RectProto bounds = 11;
optional int32 min_width = 12;
optional int32 min_height = 13;
+ optional .com.android.server.wm.TaskProto task = 14;
}
message ActivityRecordProto {
@@ -771,10 +773,11 @@
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
optional string proc_name = 1;
- optional string file = 2 [ (.android.privacy).dest = DEST_EXPLICIT ];
+ reserved 2; // file, DEST_EXPLICIT
optional int32 pid = 3;
optional int32 uid = 4;
optional bool is_user_initiated = 5;
+ optional string uri = 6 [ (.android.privacy).dest = DEST_EXPLICIT ];
}
optional Dump dump = 2;
}
diff --git a/core/proto/android/server/appwindowthumbnail.proto b/core/proto/android/server/windowcontainerthumbnail.proto
similarity index 89%
rename from core/proto/android/server/appwindowthumbnail.proto
rename to core/proto/android/server/windowcontainerthumbnail.proto
index f22cdc5..9f8ea60 100644
--- a/core/proto/android/server/appwindowthumbnail.proto
+++ b/core/proto/android/server/windowcontainerthumbnail.proto
@@ -23,9 +23,9 @@
option java_multiple_files = true;
/**
- * Represents a {@link com.android.server.wm.AppWindowThumbnail} object.
+ * Represents a {@link com.android.server.wm.WindowContainerThumbnailProto} object.
*/
-message AppWindowThumbnailProto {
+message WindowContainerThumbnailProto {
option (.android.msg_privacy).dest = DEST_AUTOMATIC;
optional int32 width = 1;
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index a346a63..c9a1829 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -20,7 +20,7 @@
import "frameworks/base/core/proto/android/content/activityinfo.proto";
import "frameworks/base/core/proto/android/content/configuration.proto";
import "frameworks/base/core/proto/android/graphics/rect.proto";
-import "frameworks/base/core/proto/android/server/appwindowthumbnail.proto";
+import "frameworks/base/core/proto/android/server/windowcontainerthumbnail.proto";
import "frameworks/base/core/proto/android/server/surfaceanimator.proto";
import "frameworks/base/core/proto/android/view/displaycutout.proto";
import "frameworks/base/core/proto/android/view/displayinfo.proto";
@@ -231,8 +231,8 @@
optional WindowTokenProto window_token = 2;
optional bool last_surface_showing = 3;
optional bool is_waiting_for_transition_start = 4;
- optional bool is_really_animating = 5;
- optional AppWindowThumbnailProto thumbnail = 6;
+ optional bool is_animating = 5;
+ optional WindowContainerThumbnailProto thumbnail = 6;
optional bool fills_parent = 7;
optional bool app_stopped = 8;
optional bool hidden_requested = 9;
diff --git a/core/proto/android/service/dropbox.proto b/core/proto/android/service/dropbox.proto
new file mode 100644
index 0000000..29fe62b
--- /dev/null
+++ b/core/proto/android/service/dropbox.proto
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.service.dropbox;
+
+import "frameworks/base/core/proto/android/privacy.proto";
+
+option java_multiple_files = true;
+
+// Dump from com.android.server.DropboxManagerService.java.
+message DropBoxManagerServiceDumpProto {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ message Entry {
+ // Time when entry was originally created.
+ optional int64 time_ms = 1 [ (.android.privacy).dest = DEST_AUTOMATIC ] ;
+ optional bytes data = 2;
+ }
+ repeated Entry entries = 1;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8fa6102..b357b3e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -497,6 +497,7 @@
<protected-broadcast android:name="android.telephony.action.CARRIER_CONFIG_CHANGED" />
<protected-broadcast android:name="android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED" />
<protected-broadcast android:name="android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED" />
+ <protected-broadcast android:name="android.telephony.action.OTA_EMERGENCY_NUMBER_DB_INSTALLED" />
<protected-broadcast android:name="android.telephony.action.SECRET_CODE" />
<protected-broadcast android:name="android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION" />
<protected-broadcast android:name="android.telephony.action.SUBSCRIPTION_PLANS_CHANGED" />
@@ -2005,6 +2006,11 @@
<!-- =========================================== -->
<eat-comment />
+ <!-- @SystemApi Allows granting runtime permissions to telephony related components.
+ @hide Used internally. -->
+ <permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS"
+ android:protectionLevel="signature|telephony" />
+
<!-- Allows modification of the telephony state - power on, mmi, etc.
Does not include placing calls.
<p>Not for use by third-party applications. -->
@@ -2274,7 +2280,7 @@
types of interactions
@hide -->
<permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"
- android:protectionLevel="signature|installer|telephony" />
+ android:protectionLevel="signature|installer|telephony|wifi" />
<!-- @SystemApi Allows an application to start its own activities, but on a different profile
associated with the user. For example, an application running on the main profile of a user
@@ -4647,6 +4653,13 @@
android:protectionLevel="normal" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
+ <!-- @hide Allow the caller to collect debugging data from processes that otherwise
+ would require USAGE_STATS. Before sharing this data with other apps, holders
+ of this permission are REQUIRED to themselves check that the caller has
+ PACKAGE_USAGE_STATS and OP_GET_USAGE_STATS. -->
+ <permission android:name="android.permission.PEEK_DROPBOX_DATA"
+ android:protectionLevel="signature|privileged" />
+
<application android:process="system"
android:persistent="true"
android:hasCode="false"
@@ -4728,19 +4741,6 @@
android:excludeFromRecents="true"
android:process=":ui">
</activity>
- <activity android:name="com.android.internal.app.DumpHeapActivity"
- android:theme="@style/Theme.Translucent.NoTitleBar"
- android:label="@string/dump_heap_title"
- android:finishOnCloseSystemDialogs="true"
- android:noHistory="true"
- android:excludeFromRecents="true"
- android:process=":ui">
- </activity>
- <provider android:name="com.android.server.am.DumpHeapProvider"
- android:authorities="com.android.server.heapdump"
- android:grantUriPermissions="true"
- android:multiprocess="false"
- android:singleUser="true" />
<activity android:name="android.accounts.ChooseAccountActivity"
android:excludeFromRecents="true"
diff --git a/core/res/res/layout/resolve_list_item.xml b/core/res/res/layout/resolve_list_item.xml
index 4857095..86f028c 100644
--- a/core/res/res/layout/resolve_list_item.xml
+++ b/core/res/res/layout/resolve_list_item.xml
@@ -54,7 +54,9 @@
android:minLines="1"
android:maxLines="1"
android:ellipsize="marquee" />
- <!-- Extended activity info to distinguish between duplicate activity names -->
+ <!-- Extended activity info to distinguish between duplicate activity names
+ or provide record w/o permission warnings.
+ -->
<TextView android:id="@android:id/text2"
android:textColor="?android:attr/textColorSecondary"
android:fontFamily="@android:string/config_bodyFontFamily"
@@ -64,7 +66,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minLines="1"
- android:maxLines="1"
+ android:maxLines="2"
android:ellipsize="marquee" />
</LinearLayout>
</LinearLayout>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 018ca7e..8558d7c 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -1274,12 +1274,9 @@
<skip />
<string name="wifi_no_internet" msgid="5198100389964214865">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>ৰ ইণ্টাৰনেটৰ এক্সেছ নাই"</string>
<string name="wifi_no_internet_detailed" msgid="8083079241212301741">"অধিক বিকল্পৰ বাবে টিপক"</string>
- <!-- no translation found for mobile_no_internet (1445208572588803493) -->
- <skip />
- <!-- no translation found for other_networks_no_internet (1553338015597653827) -->
- <skip />
- <!-- no translation found for private_dns_broken_detailed (4293356177543535578) -->
- <skip />
+ <string name="mobile_no_internet" msgid="1445208572588803493">"ম’বাইল নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই"</string>
+ <string name="other_networks_no_internet" msgid="1553338015597653827">"নেটৱৰ্কৰ কোনো ইণ্টাৰনেটৰ এক্সেছ নাই"</string>
+ <string name="private_dns_broken_detailed" msgid="4293356177543535578">"ব্যক্তিগত DNS ছাৰ্ভাৰ এক্সেছ কৰিব নোৱাৰি"</string>
<string name="captive_portal_logged_in_detailed" msgid="8489345381637456021">"সংযোগ কৰা হ’ল"</string>
<string name="network_partial_connectivity" msgid="7774883385494762741">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>ৰ সকলো সেৱাৰ এক্সেছ নাই"</string>
<string name="network_partial_connectivity_detailed" msgid="1959697814165325217">"যিকোনো প্ৰকাৰে সংযোগ কৰিবলৈ টিপক"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 4fb03d6..e74cbb1 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -299,13 +299,13 @@
<string name="permgrouplab_microphone" msgid="171539900250043464">"Μικρόφωνο"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"ηχογραφεί"</string>
<string name="permgrouprequest_microphone" msgid="9167492350681916038">"Να επιτρέπεται στην εφαρμογή <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> η εγγραφή ήχου;"</string>
- <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"Σωματική δραστηριότητα"</string>
+ <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"Σωματική δραστ/τητα"</string>
<string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"πρόσβαση στη σωματική σας δραστηριότητα"</string>
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"Να επιτρέπεται στην εφαρμογή <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> να έχει πρόσβαση στη σωματική σας δραστηριότητα;"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"Κάμερα"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"γίνεται λήψη φωτογραφιών και εγγραφή βίντεο"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"Να επιτρέπεται στην εφαρμογή <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> η λήψη φωτογραφιών και η εγγραφή βίντεο;"</string>
- <string name="permgrouplab_calllog" msgid="8798646184930388160">"Αρχεία καταγραφής κλήσεων"</string>
+ <string name="permgrouplab_calllog" msgid="8798646184930388160">"Αρχεία καταγρ. κλήσ."</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"ανάγνωση και εγγραφή αρχείου καταγραφής τηλεφωνικών κλήσεων"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"Να επιτρέπεται στην εφαρμογή <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> να έχει πρόσβαση στα αρχεία καταγραφής τηλεφωνικών κλήσεών σας;"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Τηλέφωνο"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 32530d3..02c8043 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -299,7 +299,7 @@
<string name="permgrouplab_microphone" msgid="171539900250043464">"Microphone"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"enregistrer des fichiers audio"</string>
<string name="permgrouprequest_microphone" msgid="9167492350681916038">"Autoriser <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> à enregistrer l\'audio?"</string>
- <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"données d\'activité physique"</string>
+ <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"Activité physique"</string>
<string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"accéder à vos activités physiques"</string>
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"Autoriser « <xliff:g id="APP_NAME">%1$s</xliff:g> » à accéder à vos activités physiques?"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"Appareil photo"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index 73db059..967ddd0 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1274,8 +1274,8 @@
<skip />
<string name="wifi_no_internet" msgid="5198100389964214865">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ցանցը չունի մուտք ինտերնետին"</string>
<string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Հպեք՝ ընտրանքները տեսնելու համար"</string>
- <string name="mobile_no_internet" msgid="1445208572588803493">"Բջջային ցանցում ինտերնետ կապ չկա"</string>
- <string name="other_networks_no_internet" msgid="1553338015597653827">"Ցանցում ինտերնետ կապ չկա"</string>
+ <string name="mobile_no_internet" msgid="1445208572588803493">"Բջջային ցանցը չի ապահովում ինտերնետ կապ"</string>
+ <string name="other_networks_no_internet" msgid="1553338015597653827">"Ցանցը միացված չէ ինտերնետին"</string>
<string name="private_dns_broken_detailed" msgid="4293356177543535578">"Մասնավոր DNS սերվերն անհասանելի է"</string>
<string name="captive_portal_logged_in_detailed" msgid="8489345381637456021">"Միացված է"</string>
<string name="network_partial_connectivity" msgid="7774883385494762741">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ցանցի կապը սահմանափակ է"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 462ee36..2888a53 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -304,13 +304,13 @@
<string name="permgrouprequest_storage" msgid="7885942926944299560">"לתת לאפליקציה <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> הרשאת גישה לתמונות, למדיה ולקבצים במכשיר?"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"מיקרופון"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"הקלטת אודיו"</string>
- <string name="permgrouprequest_microphone" msgid="9167492350681916038">"לתת לאפליקציה <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> הרשאה להקליט אודיו?"</string>
+ <string name="permgrouprequest_microphone" msgid="9167492350681916038">"לאשר לאפליקציית <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> להקליט אודיו?"</string>
<string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"פעילות גופנית"</string>
<string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"גישה לפעילות הגופנית שלך"</string>
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"האם לאפשר לאפליקציה <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> גישה לפעילות הגופנית שלך?"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"מצלמה"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"צילום תמונות והקלטת וידאו"</string>
- <string name="permgrouprequest_camera" msgid="1299833592069671756">"לאשר לאפליקציה של <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> לצלם תמונות וסרטונים?"</string>
+ <string name="permgrouprequest_camera" msgid="1299833592069671756">"לאשר לאפליקציית <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> לצלם תמונות וסרטונים?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"יומני שיחות"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"קריאה וכתיבה של יומן השיחות של הטלפון"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"לתת לאפליקציה <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> הרשאת גישה ליומני השיחות של הטלפון?"</string>
@@ -1318,12 +1318,9 @@
<skip />
<string name="wifi_no_internet" msgid="5198100389964214865">"ל-<xliff:g id="NETWORK_SSID">%1$s</xliff:g> אין גישה לאינטרנט"</string>
<string name="wifi_no_internet_detailed" msgid="8083079241212301741">"הקש לקבלת אפשרויות"</string>
- <!-- no translation found for mobile_no_internet (1445208572588803493) -->
- <skip />
- <!-- no translation found for other_networks_no_internet (1553338015597653827) -->
- <skip />
- <!-- no translation found for private_dns_broken_detailed (4293356177543535578) -->
- <skip />
+ <string name="mobile_no_internet" msgid="1445208572588803493">"לרשת הסלולרית אין גישה לאינטרנט"</string>
+ <string name="other_networks_no_internet" msgid="1553338015597653827">"לרשת אין גישה לאינטרנט"</string>
+ <string name="private_dns_broken_detailed" msgid="4293356177543535578">"לא ניתן לגשת לשרת DNS הפרטי"</string>
<string name="captive_portal_logged_in_detailed" msgid="8489345381637456021">"הרשת מחוברת"</string>
<string name="network_partial_connectivity" msgid="7774883385494762741">"הקישוריות של <xliff:g id="NETWORK_SSID">%1$s</xliff:g> מוגבלת"</string>
<string name="network_partial_connectivity_detailed" msgid="1959697814165325217">"כדי להתחבר למרות זאת יש להקיש"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index d1317e9..3fb6766 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -305,13 +305,13 @@
<string name="permgrouplab_camera" msgid="4820372495894586615">"ಕ್ಯಾಮರಾ"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"ಚಿತ್ರಗಳನ್ನು ತೆಗೆಯಲು, ವೀಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಲು"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"ಚಿತ್ರಗಳನ್ನು ಸೆರೆಹಿಡಿಯಲು ಮತ್ತು ವೀಡಿಯೊ ರೆಕಾರ್ಡ್ ಮಾಡಲು <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
- <string name="permgrouplab_calllog" msgid="8798646184930388160">"ಕರೆಯ ಲಾಗ್ಗಳು"</string>
+ <string name="permgrouplab_calllog" msgid="8798646184930388160">"ಕರೆಯ ಲಾಗ್"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"ಪೋನ್ ಕರೆಯ ಲಾಗ್ ಅನ್ನು ಓದಿ ಮತ್ತು ಬರೆಯಿರಿ"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"ನಿಮ್ಮ ಫೋನ್ ಕರೆಯ ಲಾಗ್ಗಳಿಗೆ ಪ್ರವೇಶ ಪಡೆಯಲು <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"ಫೋನ್"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"ಫೋನ್ ಕರೆ ಮಾಡಲು ಹಾಗೂ ನಿರ್ವಹಿಸಲು"</string>
<string name="permgrouprequest_phone" msgid="9166979577750581037">"ಫೋನ್ ಕರೆಗಳನ್ನು ಮಾಡಲು ಮತ್ತು ನಿರ್ವಹಿಸಲು <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
- <string name="permgrouplab_sensors" msgid="4838614103153567532">"ದೇಹದ ಸೆನ್ಸರ್ಗಳು"</string>
+ <string name="permgrouplab_sensors" msgid="4838614103153567532">"ದೇಹದ ಸೆನ್ಸರ್"</string>
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"ನಿಮ್ಮ ಮುಖ್ಯ ಲಕ್ಷಣಗಳ ಕುರಿತು ಸೆನ್ಸಾರ್ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಿ"</string>
<string name="permgrouprequest_sensors" msgid="6349806962814556786">"ನಿಮ್ಮ ಮುಖ್ಯ ಲಕ್ಷಣಗಳ ಕುರಿತು ಸೆನ್ಸರ್ ಡೇಟಾವನ್ನು <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ಗೆ ಅನುಮತಿಸಬೇಕೇ?"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"ವಿಂಡೋ ವಿಷಯವನ್ನು ಹಿಂಪಡೆಯುತ್ತದೆ"</string>
@@ -1274,12 +1274,9 @@
<skip />
<string name="wifi_no_internet" msgid="5198100389964214865">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿಲ್ಲ"</string>
<string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ಆಯ್ಕೆಗಳಿಗೆ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
- <!-- no translation found for mobile_no_internet (1445208572588803493) -->
- <skip />
- <!-- no translation found for other_networks_no_internet (1553338015597653827) -->
- <skip />
- <!-- no translation found for private_dns_broken_detailed (4293356177543535578) -->
- <skip />
+ <string name="mobile_no_internet" msgid="1445208572588803493">"ಮೊಬೈಲ್ ನೆಟ್ವರ್ಕ್ ಯಾವುದೇ ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ"</string>
+ <string name="other_networks_no_internet" msgid="1553338015597653827">"ನೆಟ್ವರ್ಕ್ ಇಂಟರ್ನೆಟ್ ಪ್ರವೇಶವನ್ನು ಹೊಂದಿಲ್ಲ"</string>
+ <string name="private_dns_broken_detailed" msgid="4293356177543535578">"ಖಾಸಗಿ DNS ಸರ್ವರ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
<string name="captive_portal_logged_in_detailed" msgid="8489345381637456021">"ಸಂಪರ್ಕಿಸಲಾಗಿದೆ"</string>
<string name="network_partial_connectivity" msgid="7774883385494762741">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ಸೀಮಿತ ಸಂಪರ್ಕ ಕಲ್ಪಿಸುವಿಕೆಯನ್ನು ಹೊಂದಿದೆ"</string>
<string name="network_partial_connectivity_detailed" msgid="1959697814165325217">"ಹೇಗಾದರೂ ಸಂಪರ್ಕಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index dcb766d..db54c42 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -305,7 +305,7 @@
<string name="permgrouplab_camera" msgid="4820372495894586615">"Камера"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"сүрөт жана видео тартууга"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> колдонмосуна сүрөттөр менен видеолорду тартканга уруксат бересизби?"</string>
- <string name="permgrouplab_calllog" msgid="8798646184930388160">"Чалуулар тизмелери"</string>
+ <string name="permgrouplab_calllog" msgid="8798646184930388160">"Чалуулар тизмеси"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"телефондогу чалуулар тизмесин окуу жана жазуу"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b> колдонмосуна телефондогу чалуулар тизмесин пайдаланууга уруксат берилсинби?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"Телефон"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 9d87652..5250df5 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -278,7 +278,7 @@
<string name="android_system_label" msgid="6577375335728551336">"Android സിസ്റ്റം"</string>
<string name="user_owner_label" msgid="8836124313744349203">"വ്യക്തിഗത പ്രൊഫൈലിലേക്ക് മാറുക"</string>
<string name="managed_profile_label" msgid="8947929265267690522">"ഔദ്യോഗിക പ്രൊഫൈലിലേക്ക് മാറുക"</string>
- <string name="permgrouplab_contacts" msgid="3657758145679177612">"കോൺടാക്റ്റുകൾ"</string>
+ <string name="permgrouplab_contacts" msgid="3657758145679177612">"കോൺടാക്റ്റ്"</string>
<string name="permgroupdesc_contacts" msgid="6951499528303668046">"നിങ്ങളുടെ കോൺടാക്റ്റുകൾ ആക്സസ്സ് ചെയ്യുക"</string>
<string name="permgrouprequest_contacts" msgid="6032805601881764300">"നിങ്ങളുടെ കോണ്ടാക്റ്റുകള് ആക്സസ് ചെയ്യാൻ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouplab_location" msgid="7275582855722310164">"ലൊക്കേഷൻ"</string>
@@ -299,19 +299,19 @@
<string name="permgrouplab_microphone" msgid="171539900250043464">"മൈക്രോഫോണ്"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"ഓഡിയോ റെക്കോർഡ് ചെയ്യുക"</string>
<string name="permgrouprequest_microphone" msgid="9167492350681916038">"ഓഡിയോ റെക്കോർഡ് ചെയ്യാൻ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ആപ്പിനെ അനുവദിക്കണോ?"</string>
- <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"ശാരീരിക പ്രവർത്തനം"</string>
+ <string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"കായിക പ്രവർത്തനം"</string>
<string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"ശാരീരിക പ്രവർത്തനം ആക്സസ് ചെയ്യുക"</string>
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"<b><xliff:g id="APP_NAME">%1$s</xliff:g></b>-നെ നിങ്ങളുടെ ശാരീരിക പ്രവർത്തനം ആക്സസ് ചെയ്യാൻ അനുവദിക്കണോ?"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"ക്യാമറ"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"ചിത്രങ്ങളെടുത്ത് വീഡിയോ റെക്കോർഡുചെയ്യുക"</string>
<string name="permgrouprequest_camera" msgid="1299833592069671756">"ചിത്രം എടുക്കാനും വീഡിയോ റെക്കോർഡ് ചെയ്യാനും <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ആപ്പിനെ അനുവദിക്കണോ?"</string>
- <string name="permgrouplab_calllog" msgid="8798646184930388160">"കോൾ ലോഗുകൾ"</string>
+ <string name="permgrouplab_calllog" msgid="8798646184930388160">"കോൾ ലോഗ്"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"ഫോൺ കോൾ ലോഗ് വായിക്കുകയും എഴുതുകയും ചെയ്യുക"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"നിങ്ങളുടെ ഫോൺ കോൾ ലോഗുകൾ ആക്സസ് ചെയ്യാൻ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="permgrouplab_phone" msgid="5229115638567440675">"ഫോണ്"</string>
<string name="permgroupdesc_phone" msgid="6234224354060641055">"ഫോൺ വിളിക്കുകയും നിയന്ത്രിക്കുകയും ചെയ്യുക"</string>
<string name="permgrouprequest_phone" msgid="9166979577750581037">"ഫോൺ കോളുകൾ ചെയ്യാനും അവ മാനേജ് ചെയ്യാനും <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ആപ്പിനെ അനുവദിക്കണോ?"</string>
- <string name="permgrouplab_sensors" msgid="4838614103153567532">"ബോഡി സെൻസറുകൾ"</string>
+ <string name="permgrouplab_sensors" msgid="4838614103153567532">"ബോഡി സെൻസർ"</string>
<string name="permgroupdesc_sensors" msgid="7147968539346634043">"നിങ്ങളുടെ ജീവാധാര ലക്ഷണങ്ങളെ കുറിച്ചുള്ള സെൻസർ വിവരങ്ങൾ ആക്സസ് ചെയ്യുക"</string>
<string name="permgrouprequest_sensors" msgid="6349806962814556786">"നിങ്ങളുടെ ജീവധാരണ ലക്ഷണങ്ങളെ കുറിച്ചുള്ള സെൻസർ ഡാറ്റ ആക്സസ് ചെയ്യാൻ <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> ആപ്പിനെ അനുവദിക്കണോ?"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"വിൻഡോ ഉള്ളടക്കം വീണ്ടെടുക്കുക"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 03b973b..39f614a 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1274,12 +1274,9 @@
<skip />
<string name="wifi_no_internet" msgid="5198100389964214865">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ला इंटरनेट अॅक्सेस नाही"</string>
<string name="wifi_no_internet_detailed" msgid="8083079241212301741">"पर्यायांसाठी टॅप करा"</string>
- <!-- no translation found for mobile_no_internet (1445208572588803493) -->
- <skip />
- <!-- no translation found for other_networks_no_internet (1553338015597653827) -->
- <skip />
- <!-- no translation found for private_dns_broken_detailed (4293356177543535578) -->
- <skip />
+ <string name="mobile_no_internet" msgid="1445208572588803493">"मोबाइल नेटवर्कला इंटरनेट अॅक्सेस नाही"</string>
+ <string name="other_networks_no_internet" msgid="1553338015597653827">"नेटवर्कला इंटरनेट अॅक्सेस नाही"</string>
+ <string name="private_dns_broken_detailed" msgid="4293356177543535578">"खाजगी DNS सर्व्हर अॅक्सेस करू शकत नाही"</string>
<string name="captive_portal_logged_in_detailed" msgid="8489345381637456021">"कनेक्ट केले"</string>
<string name="network_partial_connectivity" msgid="7774883385494762741">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ला मर्यादित कनेक्टिव्हिटी आहे"</string>
<string name="network_partial_connectivity_detailed" msgid="1959697814165325217">"तरीही कनेक्ट करण्यासाठी टॅप करा"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index b4079ef..cd36d53 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -1274,12 +1274,9 @@
<skip />
<string name="wifi_no_internet" msgid="5198100389964214865">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>ର ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ"</string>
<string name="wifi_no_internet_detailed" msgid="8083079241212301741">"ବିକଳ୍ପ ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
- <!-- no translation found for mobile_no_internet (1445208572588803493) -->
- <skip />
- <!-- no translation found for other_networks_no_internet (1553338015597653827) -->
- <skip />
- <!-- no translation found for private_dns_broken_detailed (4293356177543535578) -->
- <skip />
+ <string name="mobile_no_internet" msgid="1445208572588803493">"ମୋବାଇଲ୍ ନେଟ୍ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ"</string>
+ <string name="other_networks_no_internet" msgid="1553338015597653827">"ନେଟ୍ୱାର୍କରେ ଇଣ୍ଟର୍ନେଟ୍ ଆକ୍ସେସ୍ ନାହିଁ"</string>
+ <string name="private_dns_broken_detailed" msgid="4293356177543535578">"ବ୍ୟକ୍ତିଗତ DNS ସର୍ଭର୍ ଆକ୍ସେସ୍ କରିହେବ ନାହିଁ"</string>
<string name="captive_portal_logged_in_detailed" msgid="8489345381637456021">"ସଂଯୁକ୍ତ ହୋଇଛି"</string>
<string name="network_partial_connectivity" msgid="7774883385494762741">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g>ର ସୀମିତ ସଂଯୋଗ ଅଛି"</string>
<string name="network_partial_connectivity_detailed" msgid="1959697814165325217">"ତଥାପି ଯୋଗାଯୋଗ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index b238d4f..3be0900 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1318,12 +1318,9 @@
<skip />
<string name="wifi_no_internet" msgid="5198100389964214865">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> nie ma dostępu do internetu"</string>
<string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Kliknij, by wyświetlić opcje"</string>
- <!-- no translation found for mobile_no_internet (1445208572588803493) -->
- <skip />
- <!-- no translation found for other_networks_no_internet (1553338015597653827) -->
- <skip />
- <!-- no translation found for private_dns_broken_detailed (4293356177543535578) -->
- <skip />
+ <string name="mobile_no_internet" msgid="1445208572588803493">"Sieć komórkowa nie ma dostępu do internetu"</string>
+ <string name="other_networks_no_internet" msgid="1553338015597653827">"Sieć nie ma dostępu do internetu"</string>
+ <string name="private_dns_broken_detailed" msgid="4293356177543535578">"Brak dostępu do prywatnego serwera DNS"</string>
<string name="captive_portal_logged_in_detailed" msgid="8489345381637456021">"Połączono"</string>
<string name="network_partial_connectivity" msgid="7774883385494762741">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> ma ograniczoną łączność"</string>
<string name="network_partial_connectivity_detailed" msgid="1959697814165325217">"Kliknij, by mimo to nawiązać połączenie"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index f1a6136..82ec2b6 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -301,13 +301,13 @@
<string name="permgrouprequest_storage" msgid="7885942926944299560">"Permiteți <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> să acceseze fotografiile, conținutul media și fișierele de pe dispozitiv?"</string>
<string name="permgrouplab_microphone" msgid="171539900250043464">"Microfon"</string>
<string name="permgroupdesc_microphone" msgid="4988812113943554584">"înregistreze sunet"</string>
- <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Pemiteți <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> să înregistreze conținut audio?"</string>
+ <string name="permgrouprequest_microphone" msgid="9167492350681916038">"Pemiteți <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> să înregistreze audio?"</string>
<string name="permgrouplab_activityRecognition" msgid="1565108047054378642">"Activitate fizică"</string>
<string name="permgroupdesc_activityRecognition" msgid="6949472038320473478">"accesați activitatea fizică"</string>
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"Permiteți aplicației <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> să vă acceseze activitatea fizică?"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"Camera foto"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"fotografieze și să înregistreze videoclipuri"</string>
- <string name="permgrouprequest_camera" msgid="1299833592069671756">"Permiteți <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> să facă fotografii și să înregistreze videoclipuri?"</string>
+ <string name="permgrouprequest_camera" msgid="1299833592069671756">"Permiteți <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> să fotografieze și să înregistreze video?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"Jurnale de apeluri"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"să citească și să scrie jurnalul de apeluri telefonice"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"Permiteți <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> să vă acceseze jurnalele de apeluri?"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 1549f4d..18a8794 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -310,7 +310,7 @@
<string name="permgrouprequest_activityRecognition" msgid="7626438016904799383">"Povoliť aplikácii <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> prístup k vašej fyzickej aktivite?"</string>
<string name="permgrouplab_camera" msgid="4820372495894586615">"Fotoaparát"</string>
<string name="permgroupdesc_camera" msgid="3250611594678347720">"fotenie a natáčanie videí"</string>
- <string name="permgrouprequest_camera" msgid="1299833592069671756">"Povoliť aplikácii <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> snímať fotky a zaznamenávať video?"</string>
+ <string name="permgrouprequest_camera" msgid="1299833592069671756">"Chcete povoliť aplikácii <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> fotiť a nahrávať video?"</string>
<string name="permgrouplab_calllog" msgid="8798646184930388160">"Zoznam hovorov"</string>
<string name="permgroupdesc_calllog" msgid="3006237336748283775">"čítať a zapisovať do zoznamu hovorov"</string>
<string name="permgrouprequest_calllog" msgid="8487355309583773267">"Povoliť aplikácii <b><xliff:g id="APP_NAME">%1$s</xliff:g></b> prístup k zoznamu hovorov?"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 5431796..fd77532 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1234,7 +1234,7 @@
<string name="volume_unknown" msgid="1400219669770445902">"ระดับเสียง"</string>
<string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"ระดับบลูทูธ"</string>
<string name="volume_icon_description_ringer" msgid="3326003847006162496">"ระดับเสียงเรียกเข้า"</string>
- <string name="volume_icon_description_incall" msgid="8890073218154543397">"ปริมาณการโทร"</string>
+ <string name="volume_icon_description_incall" msgid="8890073218154543397">"ระดับเสียงการโทร"</string>
<string name="volume_icon_description_media" msgid="4217311719665194215">"ระดับเสียงของสื่อ"</string>
<string name="volume_icon_description_notification" msgid="7044986546477282274">"ระดับเสียงของการแจ้งเตือน"</string>
<string name="ringtone_default" msgid="3789758980357696936">"เสียงเรียกเข้าเริ่มต้น"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index 776595f..97660b4 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -1274,12 +1274,9 @@
<skip />
<string name="wifi_no_internet" msgid="5198100389964214865">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> کو انٹرنیٹ تک رسائی حاصل نہیں ہے"</string>
<string name="wifi_no_internet_detailed" msgid="8083079241212301741">"اختیارات کیلئے تھپتھپائیں"</string>
- <!-- no translation found for mobile_no_internet (1445208572588803493) -->
- <skip />
- <!-- no translation found for other_networks_no_internet (1553338015597653827) -->
- <skip />
- <!-- no translation found for private_dns_broken_detailed (4293356177543535578) -->
- <skip />
+ <string name="mobile_no_internet" msgid="1445208572588803493">"موبائل نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے"</string>
+ <string name="other_networks_no_internet" msgid="1553338015597653827">"نیٹ ورک کو انٹرنیٹ تک رسائی حاصل نہیں ہے"</string>
+ <string name="private_dns_broken_detailed" msgid="4293356177543535578">"نجی DNS سرور تک رسائی حاصل نہیں کی جا سکی"</string>
<string name="captive_portal_logged_in_detailed" msgid="8489345381637456021">"منسلک ہے"</string>
<string name="network_partial_connectivity" msgid="7774883385494762741">"<xliff:g id="NETWORK_SSID">%1$s</xliff:g> کی کنیکٹوٹی محدود ہے"</string>
<string name="network_partial_connectivity_detailed" msgid="1959697814165325217">"بہر حال منسلک کرنے کے لیے تھپتھپائیں"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index eaf93eb..9ca98c5 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3705,7 +3705,7 @@
name is separated by comma.
Example: "com.android.phone,com.android.stk,com.android.providers.telephony"
-->
- <string name="config_telephonyPackages" translatable="false">"com.android.phone,com.android.stk,com.android.providers.telephony,com.android.ons"</string>
+ <string name="config_telephonyPackages" translatable="false">"com.android.phone,com.android.stk,com.android.providers.telephony,com.android.ons,com.android.cellbroadcastservice"</string>
<!-- The package name for the default system wifi app.
This package must be trusted, as it has the permissions to control wifi
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d39d507..585c4bb 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -5440,4 +5440,6 @@
<!-- ChooserActivity - Alphabetically sorted apps list label. [CHAR LIMIT=NONE] -->
<string name="chooser_all_apps_button_label">Apps list</string>
+ <!-- Prompt for the USB device resolver dialog with warning text for USB device dialogs. [CHAR LIMIT=200] -->
+ <string name="usb_device_resolve_prompt_warn">This app has not been granted record permission but could capture audio through this USB device.</string>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 8d96c79..1313912 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3876,4 +3876,6 @@
<java-symbol type="bool" name="config_showBuiltinWirelessChargingAnim" />
+ <java-symbol type="string" name="usb_device_resolve_prompt_warn" />
+
</resources>
diff --git a/core/tests/coretests/src/android/content/ContentResolverTest.java b/core/tests/coretests/src/android/content/ContentResolverTest.java
index f14f289..e140ad2 100644
--- a/core/tests/coretests/src/android/content/ContentResolverTest.java
+++ b/core/tests/coretests/src/android/content/ContentResolverTest.java
@@ -82,22 +82,23 @@
final AssetFileDescriptor afd = new AssetFileDescriptor(
new ParcelFileDescriptor(mImage.getFileDescriptor()), 0, mSize, null);
- when(mProvider.openTypedAssetFile(any(), any(), any(), any(), any())).thenReturn(afd);
+ when(mProvider.openTypedAssetFile(any(), any(), any(), any(), any(), any())).thenReturn(
+ afd);
}
- private static void assertImageAspectAndContents(Bitmap bitmap) {
+ private static void assertImageAspectAndContents(int width, int height, Bitmap bitmap) {
// And correct aspect ratio
- final int before = (100 * 1280) / 960;
+ final int before = (100 * width) / height;
final int after = (100 * bitmap.getWidth()) / bitmap.getHeight();
assertEquals(before, after);
// And scaled correctly
final int halfX = bitmap.getWidth() / 2;
final int halfY = bitmap.getHeight() / 2;
- assertEquals(Color.BLUE, bitmap.getPixel(halfX - 10, halfY - 10));
- assertEquals(Color.RED, bitmap.getPixel(halfX + 10, halfY - 10));
- assertEquals(Color.RED, bitmap.getPixel(halfX - 10, halfY + 10));
- assertEquals(Color.RED, bitmap.getPixel(halfX + 10, halfY + 10));
+ assertEquals(Color.BLUE, bitmap.getPixel(halfX - 5, halfY - 5));
+ assertEquals(Color.RED, bitmap.getPixel(halfX + 5, halfY - 5));
+ assertEquals(Color.RED, bitmap.getPixel(halfX - 5, halfY + 5));
+ assertEquals(Color.RED, bitmap.getPixel(halfX + 5, halfY + 5));
}
@Test
@@ -112,7 +113,7 @@
assertEquals(1280, res.getWidth());
assertEquals(960, res.getHeight());
- assertImageAspectAndContents(res);
+ assertImageAspectAndContents(1280, 960, res);
}
@Test
@@ -127,7 +128,7 @@
assertTrue(res.getWidth() <= 640);
assertTrue(res.getHeight() <= 480);
- assertImageAspectAndContents(res);
+ assertImageAspectAndContents(1280, 960, res);
}
@Test
@@ -142,7 +143,7 @@
assertTrue(res.getWidth() <= 640);
assertTrue(res.getHeight() <= 480);
- assertImageAspectAndContents(res);
+ assertImageAspectAndContents(1280, 960, res);
}
@Test
@@ -157,7 +158,23 @@
assertEquals(32, res.getWidth());
assertEquals(24, res.getHeight());
- assertImageAspectAndContents(res);
+ assertImageAspectAndContents(32, 24, res);
+ }
+
+ @Test
+ public void testLoadThumbnail_Large() throws Exception {
+ // Test very large and extreme ratio image
+ initImage(1080, 30000);
+
+ Bitmap res = ContentResolver.loadThumbnail(mClient,
+ Uri.parse("content://com.example/"), new Size(1080, 540), null,
+ ImageDecoder.ALLOCATOR_SOFTWARE);
+
+ // Size should be much smaller
+ assertTrue(res.getWidth() <= 2160);
+ assertTrue(res.getHeight() <= 1080);
+
+ assertImageAspectAndContents(1080, 30000, res);
}
@Test
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationTest.java b/core/tests/coretests/src/android/content/res/ConfigurationTest.java
index 4a93f42..c231e61 100644
--- a/core/tests/coretests/src/android/content/res/ConfigurationTest.java
+++ b/core/tests/coretests/src/android/content/res/ConfigurationTest.java
@@ -16,6 +16,18 @@
package android.content.res;
+import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOW_CONFIG_ROTATION;
+import static android.app.WindowConfiguration.WINDOW_CONFIG_WINDOWING_MODE;
+import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
+import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
+import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
+import static android.view.Surface.ROTATION_90;
+
import android.content.Context;
import android.os.LocaleList;
import android.platform.test.annotations.Presubmit;
@@ -104,6 +116,38 @@
read.getLocales().indexOf(urduExtension) != -1);
}
+ @Test
+ public void testMaskedSet() {
+ Configuration config = new Configuration();
+ Configuration other = new Configuration();
+ config.smallestScreenWidthDp = 100;
+ config.orientation = ORIENTATION_LANDSCAPE;
+ config.windowConfiguration.setRotation(ROTATION_90);
+ other.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ other.orientation = ORIENTATION_PORTRAIT;
+
+ // no change
+ config.setTo(other, 0, 0);
+ assertEquals(100, config.smallestScreenWidthDp);
+ assertEquals(ORIENTATION_LANDSCAPE, config.orientation);
+ assertEquals(ROTATION_90, config.windowConfiguration.getRotation());
+
+ final int justOrientationAndWindowConfig = CONFIG_ORIENTATION | CONFIG_WINDOW_CONFIGURATION;
+ config.setTo(other, justOrientationAndWindowConfig, WINDOW_CONFIG_WINDOWING_MODE);
+ assertEquals(100, config.smallestScreenWidthDp);
+ assertEquals(other.orientation, config.orientation);
+ assertEquals(other.windowConfiguration.getWindowingMode(),
+ config.windowConfiguration.getWindowingMode());
+ assertEquals(ROTATION_90, config.windowConfiguration.getRotation());
+
+ // unset
+ final int justSmallestSwAndWindowConfig =
+ CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_WINDOW_CONFIGURATION;
+ config.setTo(other, justSmallestSwAndWindowConfig, WINDOW_CONFIG_ROTATION);
+ assertEquals(ROTATION_UNDEFINED, config.windowConfiguration.getRotation());
+ assertEquals(SMALLEST_SCREEN_WIDTH_DP_UNDEFINED, config.smallestScreenWidthDp);
+ }
+
private void writeToProto(File f, Configuration config) throws Exception {
final AtomicFile af = new AtomicFile(f);
FileOutputStream fos = af.startWrite();
diff --git a/core/tests/coretests/src/android/provider/DeviceConfigTest.java b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
index 1f2dfe0..0c83390 100644
--- a/core/tests/coretests/src/android/provider/DeviceConfigTest.java
+++ b/core/tests/coretests/src/android/provider/DeviceConfigTest.java
@@ -388,6 +388,13 @@
assertThat(properties.getKeyset()).containsExactly(KEY, KEY2);
assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE3);
assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
+
+ DeviceConfig.setProperty(NAMESPACE, KEY3, VALUE, false);
+ properties = DeviceConfig.getProperties(NAMESPACE);
+ assertThat(properties.getKeyset()).containsExactly(KEY, KEY2, KEY3);
+ assertThat(properties.getString(KEY, DEFAULT_VALUE)).isEqualTo(VALUE3);
+ assertThat(properties.getString(KEY2, DEFAULT_VALUE)).isEqualTo(VALUE2);
+ assertThat(properties.getString(KEY3, DEFAULT_VALUE)).isEqualTo(VALUE);
}
@Test
diff --git a/core/tests/coretests/src/android/provider/TestDocumentsProvider.java b/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
index 1bd8ff6..5f640be 100644
--- a/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
+++ b/core/tests/coretests/src/android/provider/TestDocumentsProvider.java
@@ -93,12 +93,14 @@
}
@Override
- protected int enforceReadPermissionInner(Uri uri, String callingPkg, IBinder callerToken) {
+ protected int enforceReadPermissionInner(Uri uri, String callingPkg,
+ @Nullable String callingFeatureId, IBinder callerToken) {
return AppOpsManager.MODE_ALLOWED;
}
@Override
- protected int enforceWritePermissionInner(Uri uri, String callingPkg, IBinder callerToken) {
+ protected int enforceWritePermissionInner(Uri uri, String callingPkg,
+ @Nullable String callingFeatureId, IBinder callerToken) {
return AppOpsManager.MODE_ALLOWED;
}
diff --git a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java
index e41df418..a2191b5 100644
--- a/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java
+++ b/core/tests/coretests/src/com/android/internal/app/ResolverWrapperAdapter.java
@@ -39,7 +39,7 @@
ResolverListCommunicator resolverListCommunicator) {
super(context, payloadIntents, initialIntents, rList, filterLastUsed,
resolverListController,
- useLayoutForBrowsables, resolverListCommunicator);
+ useLayoutForBrowsables, resolverListCommunicator, false);
}
public CountingIdlingResource getLabelIdlingResource() {
diff --git a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
index 0be5009..9f68ef3 100644
--- a/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
+++ b/core/tests/coretests/src/com/android/internal/statusbar/RegisterStatusBarResultTest.java
@@ -18,7 +18,6 @@
import static com.google.common.truth.Truth.assertThat;
-import android.graphics.Rect;
import android.os.Binder;
import android.os.Parcel;
import android.os.UserHandle;
@@ -27,6 +26,8 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.internal.view.AppearanceRegion;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -47,19 +48,17 @@
final RegisterStatusBarResult original = new RegisterStatusBarResult(iconMap,
0x2 /* disabledFlags1 */,
- 0x4 /* systemUiVisibility */,
+ 0x4 /* appearance */,
+ new AppearanceRegion[0] /* appearanceRegions */,
0x8 /* imeWindowVis */,
0x10 /* imeBackDisposition */,
false /* showImeSwitcher */,
0x20 /* disabledFlags2 */,
- 0x40 /* fullscreenStackSysUiVisibility */,
- 0x80 /* dockedStackSysUiVisibility */,
new Binder() /* imeToken */,
- new Rect(0x100, 0x200, 0x400, 0x800) /* fullscreenStackBounds */,
- new Rect(0x1000, 0x2000, 0x4000, 0x8000) /* dockedStackBounds */,
true /* navbarColorManagedByIme */,
true /* appFullscreen */,
- true /* appImmersive */);
+ true /* appImmersive */,
+ new int[0] /* transientBarTypes */);
final RegisterStatusBarResult copy = clone(original);
@@ -69,21 +68,17 @@
.isEqualTo(original.mIcons.get(dumyIconKey).user);
assertThat(copy.mDisabledFlags1).isEqualTo(original.mDisabledFlags1);
- assertThat(copy.mSystemUiVisibility).isEqualTo(original.mSystemUiVisibility);
+ assertThat(copy.mAppearance).isEqualTo(original.mAppearance);
+ assertThat(copy.mAppearanceRegions).isEqualTo(original.mAppearanceRegions);
assertThat(copy.mImeWindowVis).isEqualTo(original.mImeWindowVis);
assertThat(copy.mImeBackDisposition).isEqualTo(original.mImeBackDisposition);
assertThat(copy.mShowImeSwitcher).isEqualTo(original.mShowImeSwitcher);
assertThat(copy.mDisabledFlags2).isEqualTo(original.mDisabledFlags2);
- assertThat(copy.mFullscreenStackSysUiVisibility)
- .isEqualTo(original.mFullscreenStackSysUiVisibility);
- assertThat(copy.mDockedStackSysUiVisibility)
- .isEqualTo(original.mDockedStackSysUiVisibility);
assertThat(copy.mImeToken).isSameAs(original.mImeToken);
- assertThat(copy.mFullscreenStackBounds).isEqualTo(original.mFullscreenStackBounds);
- assertThat(copy.mDockedStackBounds).isEqualTo(original.mDockedStackBounds);
assertThat(copy.mNavbarColorManagedByIme).isEqualTo(original.mNavbarColorManagedByIme);
assertThat(copy.mAppFullscreen).isEqualTo(original.mAppFullscreen);
assertThat(copy.mAppImmersive).isEqualTo(original.mAppImmersive);
+ assertThat(copy.mTransientBarTypes).isEqualTo(original.mTransientBarTypes);
}
private RegisterStatusBarResult clone(RegisterStatusBarResult original) {
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index b3f6fdb..364e4ea 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -46,10 +46,12 @@
import android.os.Binder;
import android.os.RemoteException;
import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
import android.view.WindowManagerGlobal;
import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -70,6 +72,8 @@
*/
@RunWith(AndroidJUnit4.class)
@MediumTest
+@Presubmit
+@FlakyTest(bugId = 143153552)
public class ActivityThreadClientTest {
@Test
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index dceb243..80098c5 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -174,6 +174,7 @@
<assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="incidentd" />
<assign-permission name="android.permission.INTERACT_ACROSS_USERS" uid="incidentd" />
<assign-permission name="android.permission.REQUEST_INCIDENT_REPORT_APPROVAL" uid="incidentd" />
+ <assign-permission name="android.permission.PEEK_DROPBOX_DATA" uid="incidentd" />
<assign-permission name="android.permission.ACCESS_LOWPAN_STATE" uid="lowpan" />
<assign-permission name="android.permission.MANAGE_LOWPAN_INTERFACES" uid="lowpan" />
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index a0215e1..77b0dba 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -365,7 +365,7 @@
<permission name="android.permission.CHANGE_CONFIGURATION"/>
<permission name="android.permission.CONNECTIVITY_INTERNAL"/>
<permission name="android.permission.DUMP"/>
- <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ <permission name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
<permission name="android.permission.INTERNAL_SYSTEM_WINDOW"/>
<permission name="android.permission.LOCAL_MAC_ADDRESS"/>
<permission name="android.permission.MANAGE_USERS"/>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 342259d..5b9b703 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -169,12 +169,6 @@
"group": "WM_DEBUG_RESIZE",
"at": "com\/android\/server\/wm\/WindowState.java"
},
- "-1822611824": {
- "message": "\tRemove token=%s",
- "level": "DEBUG",
- "group": "WM_DEBUG_REMOTE_ANIMATIONS",
- "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
- },
"-1797409732": {
"message": "Skipping %s because %s",
"level": "VERBOSE",
@@ -307,12 +301,6 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
- "-1483752006": {
- "message": " THUMBNAIL %s: CREATE",
- "level": "INFO",
- "group": "WM_SHOW_TRANSACTIONS",
- "at": "com\/android\/server\/wm\/AppWindowThumbnail.java"
- },
"-1471946192": {
"message": "Marking app token %s with replacing child windows.",
"level": "DEBUG",
@@ -421,6 +409,12 @@
"group": "WM_SHOW_TRANSACTIONS",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-1248645819": {
+ "message": "\tAdd container=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_REMOTE_ANIMATIONS",
+ "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
+ },
"-1219773477": {
"message": "setInputConsumerEnabled(%s): mCanceled=%b",
"level": "DEBUG",
@@ -493,12 +487,6 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/RootWindowContainer.java"
},
- "-1099052739": {
- "message": "\tAdd token=%s",
- "level": "DEBUG",
- "group": "WM_DEBUG_REMOTE_ANIMATIONS",
- "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
- },
"-1089874824": {
"message": "SURFACE SHOW (performLayout): %s",
"level": "INFO",
@@ -721,6 +709,12 @@
"group": "WM_DEBUG_SCREEN_ON",
"at": "com\/android\/server\/wm\/DisplayContent.java"
},
+ "-633961578": {
+ "message": "applyAnimation: transition animation is disabled or skipped. container=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ },
"-622997754": {
"message": "postWindowRemoveCleanupLocked: %s",
"level": "VERBOSE",
@@ -883,12 +877,6 @@
"group": "WM_DEBUG_ADD_REMOVE",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
- "-253016819": {
- "message": "applyAnimation: transition animation is disabled or skipped. atoken=%s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
- "at": "com\/android\/server\/wm\/ActivityRecord.java"
- },
"-251259736": {
"message": "No longer freezing: %s",
"level": "VERBOSE",
@@ -919,12 +907,6 @@
"group": "WM_DEBUG_APP_TRANSITIONS",
"at": "com\/android\/server\/wm\/AppTransitionController.java"
},
- "-121104356": {
- "message": "Remove %s: mSurfaceController=%s mAnimatingExit=%b mRemoveOnExit=%b mHasSurface=%b surfaceShowing=%b animating=%b app-animation=%b mWillReplaceWindow=%b inPendingTransaction=%b mDisplayFrozen=%b callers=%s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_APP_TRANSITIONS",
- "at": "com\/android\/server\/wm\/WindowState.java"
- },
"-116086365": {
"message": "******************** ENABLING SCREEN!",
"level": "INFO",
@@ -961,6 +943,12 @@
"group": "WM_SHOW_TRANSACTIONS",
"at": "com\/android\/server\/wm\/Session.java"
},
+ "-33096143": {
+ "message": "applyAnimation: transition animation is disabled or skipped. container=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
+ "at": "com\/android\/server\/wm\/WindowContainer.java"
+ },
"-29233992": {
"message": "SURFACE CLEAR CROP: %s",
"level": "INFO",
@@ -1303,6 +1291,12 @@
"group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
"at": "com\/android\/server\/wm\/AppTransition.java"
},
+ "531242746": {
+ "message": " THUMBNAIL %s: CREATE",
+ "level": "INFO",
+ "group": "WM_SHOW_TRANSACTIONS",
+ "at": "com\/android\/server\/wm\/WindowContainerThumbnail.java"
+ },
"539077569": {
"message": "Clear freezing of %s force=%b",
"level": "VERBOSE",
@@ -1333,6 +1327,12 @@
"group": "WM_DEBUG_REMOTE_ANIMATIONS",
"at": "com\/android\/server\/wm\/RemoteAnimationController.java"
},
+ "594260654": {
+ "message": "Remove %s: mSurfaceController=%s mAnimatingExit=%b mRemoveOnExit=%b mHasSurface=%b surfaceShowing=%b animating=%b app-animation=%b mWillReplaceWindow=%b mDisplayFrozen=%b callers=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_APP_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/WindowState.java"
+ },
"600140673": {
"message": "checkBootAnimationComplete: Waiting for anim complete",
"level": "INFO",
@@ -1375,6 +1375,12 @@
"group": "WM_SHOW_TRANSACTIONS",
"at": "com\/android\/server\/wm\/WindowSurfaceController.java"
},
+ "638429464": {
+ "message": "\tRemove container=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_REMOTE_ANIMATIONS",
+ "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
+ },
"644675193": {
"message": "Real start recents",
"level": "DEBUG",
@@ -1465,12 +1471,6 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
- "815803557": {
- "message": "applyAnimation: atoken=%s",
- "level": "VERBOSE",
- "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
- "at": "com\/android\/server\/wm\/ActivityRecord.java"
- },
"829434921": {
"message": "Draw state now committed in %s",
"level": "VERBOSE",
@@ -1543,6 +1543,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "972354148": {
+ "message": "\tcontainer=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_REMOTE_ANIMATIONS",
+ "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
+ },
"1001904964": {
"message": "***** BOOT TIMEOUT: forcing display enabled",
"level": "WARN",
@@ -1675,12 +1681,6 @@
"group": "WM_DEBUG_FOCUS",
"at": "com\/android\/server\/wm\/DisplayContent.java"
},
- "1358786604": {
- "message": "No thumbnail header bitmap for: %d",
- "level": "DEBUG",
- "group": "WM_DEBUG_APP_TRANSITIONS",
- "at": "com\/android\/server\/wm\/ActivityRecord.java"
- },
"1364498663": {
"message": "notifyAppResumed: wasStopped=%b %s",
"level": "VERBOSE",
@@ -1795,11 +1795,11 @@
"group": "WM_DEBUG_RECENTS_ANIMATIONS",
"at": "com\/android\/server\/wm\/RecentsAnimationController.java"
},
- "1531527061": {
- "message": "createAnimationAdapter(): token=%s",
+ "1528528509": {
+ "message": "No thumbnail header bitmap for: %s",
"level": "DEBUG",
- "group": "WM_DEBUG_REMOTE_ANIMATIONS",
- "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
+ "group": "WM_DEBUG_APP_TRANSITIONS",
+ "at": "com\/android\/server\/wm\/ActivityRecord.java"
},
"1563755163": {
"message": "Permission Denial: %s from pid=%d, uid=%d requires %s",
@@ -1819,6 +1819,12 @@
"group": "WM_DEBUG_ADD_REMOVE",
"at": "com\/android\/server\/wm\/WindowState.java"
},
+ "1584270979": {
+ "message": "applyAnimation: container=%s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_APP_TRANSITIONS_ANIM",
+ "at": "com\/android\/server\/wm\/WindowContainer.java"
+ },
"1589610525": {
"message": "applyAnimation NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS: anim=%s transit=%s isEntrance=true Callers=%s",
"level": "VERBOSE",
@@ -1909,11 +1915,11 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "1804869745": {
+ "1831008694": {
"message": "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s surfaceInsets=%s",
"level": "DEBUG",
"group": "WM_DEBUG_APP_TRANSITIONS",
- "at": "com\/android\/server\/wm\/ActivityRecord.java"
+ "at": "com\/android\/server\/wm\/WindowContainer.java"
},
"1836214582": {
"message": "startingData was nulled out before handling mAddStartingWindow: %s",
@@ -1939,12 +1945,6 @@
"group": "WM_DEBUG_SCREEN_ON",
"at": "com\/android\/server\/wm\/DisplayPolicy.java"
},
- "1865246212": {
- "message": "\tapp=%s",
- "level": "DEBUG",
- "group": "WM_DEBUG_REMOTE_ANIMATIONS",
- "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
- },
"1866772666": {
"message": "SAFE MODE not enabled",
"level": "INFO",
@@ -2017,6 +2017,12 @@
"group": "WM_DEBUG_STARTING_WINDOW",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "2022422429": {
+ "message": "createAnimationAdapter(): container=%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_REMOTE_ANIMATIONS",
+ "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
+ },
"2028163120": {
"message": "applyAnimation: anim=%s nextAppTransition=ANIM_SCALE_UP transit=%s isEntrance=%s Callers=%s",
"level": "VERBOSE",
diff --git a/data/keyboards/Vendor_1532_Product_0900.kl b/data/keyboards/Vendor_1532_Product_0900.kl
index c2fc1b4..4c6c4dd 100644
--- a/data/keyboards/Vendor_1532_Product_0900.kl
+++ b/data/keyboards/Vendor_1532_Product_0900.kl
@@ -20,13 +20,19 @@
key 308 BUTTON_Y
key 310 BUTTON_L1
key 311 BUTTON_R1
-key 316 BUTTON_MODE
key 317 BUTTON_THUMBL
key 318 BUTTON_THUMBR
key 158 BACK
key 172 HOME
+# Left arrow to the left of the "power" key
+key 0x13a BUTTON_SELECT
+# Right arrow to the right of the "power" key
+key 0x13b BUTTON_START
+# Power key
+key 0x13c BUTTON_MODE
+
axis 0x00 X
axis 0x01 Y
axis 0x02 Z
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index b7316ab..109d863 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -1114,7 +1114,7 @@
* Return the width for stroking.
* <p />
* A value of 0 strokes in hairline mode.
- * Hairlines always draws a single pixel independent of the canva's matrix.
+ * Hairlines always draws a single pixel independent of the canvas's matrix.
*
* @return the paint's stroke width, used whenever the paint's style is
* Stroke or StrokeAndFill.
@@ -1126,7 +1126,7 @@
/**
* Set the width for stroking.
* Pass 0 to stroke in hairline mode.
- * Hairlines always draws a single pixel independent of the canva's matrix.
+ * Hairlines always draws a single pixel independent of the canvas's matrix.
*
* @param width set the paint's stroke width, used whenever the paint's
* style is Stroke or StrokeAndFill.
@@ -1958,8 +1958,8 @@
* <code>
* Paint paint = new Paint();
* paint.setStartHyphenEdit(Paint.START_HYPHEN_EDIT_INSERT_HYPHEN);
- * paint.measureText("abc", 0, 3); // Returns the width of "‐abc"
- * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "‐abc"
+ * paint.measureText("abc", 0, 3); // Returns the width of "-abc"
+ * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "-abc"
* </code>
* </pre>
*
@@ -1985,8 +1985,8 @@
* <code>
* Paint paint = new Paint();
* paint.setEndHyphenEdit(Paint.END_HYPHEN_EDIT_INSERT_HYPHEN);
- * paint.measureText("abc", 0, 3); // Returns the width of "abc‐"
- * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "abc‐"
+ * paint.measureText("abc", 0, 3); // Returns the width of "abc-"
+ * Canvas.drawText("abc", 0, 3, 0f, 0f, paint); // Draws "abc-"
* </code>
* </pre>
*
diff --git a/graphics/java/android/graphics/drawable/DrawableWrapper.java b/graphics/java/android/graphics/drawable/DrawableWrapper.java
index 64fc704..6c90c4c 100644
--- a/graphics/java/android/graphics/drawable/DrawableWrapper.java
+++ b/graphics/java/android/graphics/drawable/DrawableWrapper.java
@@ -364,6 +364,13 @@
}
@Override
+ public void jumpToCurrentState() {
+ if (mDrawable != null) {
+ mDrawable.jumpToCurrentState();
+ }
+ }
+
+ @Override
protected boolean onLevelChange(int level) {
return mDrawable != null && mDrawable.setLevel(level);
}
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index c6586ec..45b2de5 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -784,7 +784,9 @@
mFillPaint.setDither(st.mDither);
mFillPaint.setColorFilter(colorFilter);
if (colorFilter != null && st.mSolidColors == null) {
- mFillPaint.setColor(mAlpha << 24);
+ // If we don't have a solid color and we don't have a gradient,
+ // the app is stroking the shape, set the color to transparent
+ mFillPaint.setColor(st.mGradientColors != null ? mAlpha << 24 : 0);
}
if (haveStroke) {
mStrokePaint.setAlpha(currStrokeAlpha);
diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp
index 40bff88..3681c69 100644
--- a/libs/hwui/HardwareBitmapUploader.cpp
+++ b/libs/hwui/HardwareBitmapUploader.cpp
@@ -302,6 +302,7 @@
switch (skBitmap.info().colorType()) {
case kRGBA_8888_SkColorType:
formatInfo.isSupported = true;
+ [[fallthrough]];
// ARGB_4444 is upconverted to RGBA_8888
case kARGB_4444_SkColorType:
formatInfo.pixelFormat = PIXEL_FORMAT_RGBA_8888;
diff --git a/libs/hwui/SkiaCanvas.h b/libs/hwui/SkiaCanvas.h
index ec83a19..1eb089d 100644
--- a/libs/hwui/SkiaCanvas.h
+++ b/libs/hwui/SkiaCanvas.h
@@ -136,7 +136,6 @@
const Paint* paint) override;
virtual double drawAnimatedImage(AnimatedImageDrawable* imgDrawable) override;
- virtual bool drawTextAbsolutePos() const override { return true; }
virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override;
virtual void drawRoundRect(uirenderer::CanvasPropertyPrimitive* left,
diff --git a/libs/hwui/TreeInfo.cpp b/libs/hwui/TreeInfo.cpp
index dc53dd6..750f869 100644
--- a/libs/hwui/TreeInfo.cpp
+++ b/libs/hwui/TreeInfo.cpp
@@ -24,7 +24,6 @@
: mode(mode)
, prepareTextures(mode == MODE_FULL)
, canvasContext(canvasContext)
- , damageGenerationId(canvasContext.getFrameNumber())
, disableForceDark(canvasContext.useForceDark() ? 0 : 1)
, screenSize(canvasContext.getNextFrameSize()) {}
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index b98ffca..c138a32 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -95,18 +95,10 @@
void operator()(size_t start, size_t end) {
auto glyphFunc = [&](uint16_t* text, float* positions) {
- if (canvas->drawTextAbsolutePos()) {
- for (size_t i = start, textIndex = 0, posIndex = 0; i < end; i++) {
- text[textIndex++] = layout.getGlyphId(i);
- positions[posIndex++] = x + layout.getX(i);
- positions[posIndex++] = y + layout.getY(i);
- }
- } else {
- for (size_t i = start, textIndex = 0, posIndex = 0; i < end; i++) {
- text[textIndex++] = layout.getGlyphId(i);
- positions[posIndex++] = layout.getX(i);
- positions[posIndex++] = layout.getY(i);
- }
+ for (size_t i = start, textIndex = 0, posIndex = 0; i < end; i++) {
+ text[textIndex++] = layout.getGlyphId(i);
+ positions[posIndex++] = x + layout.getX(i);
+ positions[posIndex++] = y + layout.getY(i);
}
};
@@ -166,9 +158,6 @@
minikin::MinikinRect bounds;
layout.getBounds(&bounds);
- if (!drawTextAbsolutePos()) {
- bounds.offset(x, y);
- }
// Set align to left for drawing, as we don't want individual
// glyphs centered or right-aligned; the offset above takes
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index b90a4a3d..27dfed3 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -253,15 +253,6 @@
virtual void drawPicture(const SkPicture& picture) = 0;
/**
- * Specifies if the positions passed to ::drawText are absolute or relative
- * to the (x,y) value provided.
- *
- * If true the (x,y) values are ignored. Otherwise, those (x,y) values need
- * to be added to each glyph's position to get its absolute position.
- */
- virtual bool drawTextAbsolutePos() const = 0;
-
- /**
* Draws a VectorDrawable onto the canvas.
*/
virtual void drawVectorDrawable(VectorDrawableRoot* tree) = 0;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index e5c502c..15e0c8d 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -303,6 +303,7 @@
info.damageAccumulator = &mDamageAccumulator;
info.layerUpdateQueue = &mLayerUpdateQueue;
+ info.damageGenerationId = mDamageId++;
info.out.canDrawThisFrame = true;
mAnimationContext->startFrame(info.mode);
@@ -478,7 +479,8 @@
if (didDraw) {
swap.damage = windowDirty;
} else {
- swap.damage = SkRect::MakeWH(INT_MAX, INT_MAX);
+ float max = static_cast<float>(INT_MAX);
+ swap.damage = SkRect::MakeWH(max, max);
}
swap.swapCompletedTime = systemTime(SYSTEM_TIME_MONOTONIC);
swap.vsyncTime = mRenderThread.timeLord().latestVsync();
@@ -702,7 +704,7 @@
surface->query(NATIVE_WINDOW_WIDTH, &width);
surface->query(NATIVE_WINDOW_HEIGHT, &height);
- return width == mLastFrameWidth && height == mLastFrameHeight;
+ return width != mLastFrameWidth || height != mLastFrameHeight;
}
void CanvasContext::setRenderAheadDepth(int renderAhead) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 6e3e43a..b192d46 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -245,6 +245,7 @@
// Need at least 4 because we do quad buffer. Add a 5th for good measure.
RingBuffer<SwapHistory, 5> mSwapHistory;
int64_t mFrameNumber = -1;
+ int64_t mDamageId = 0;
// last vsync for a dropped frame due to stuffed queue
nsecs_t mLastDropVsync = 0;
diff --git a/location/java/android/location/ILocationListener.aidl b/location/java/android/location/ILocationListener.aidl
index ec11345..8479caf 100644
--- a/location/java/android/location/ILocationListener.aidl
+++ b/location/java/android/location/ILocationListener.aidl
@@ -31,8 +31,6 @@
void onProviderEnabled(String provider);
@UnsupportedAppUsage
void onProviderDisabled(String provider);
-
- // --- deprecated ---
- @UnsupportedAppUsage
- void onStatusChanged(String provider, int status, in Bundle extras);
+ // called when the listener is removed from the server side; no further callbacks are expected
+ void onRemoved();
}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index d3db9d8..b7dd543 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -230,7 +230,7 @@
public static final String METADATA_SETTINGS_FOOTER_STRING =
"com.android.settings.location.FOOTER_STRING";
- private static final long GET_CURRENT_LOCATION_TIMEOUT_MS = 30 * 1000;
+ private static final long GET_CURRENT_LOCATION_MAX_TIMEOUT_MS = 30 * 1000;
private final Context mContext;
@@ -630,7 +630,10 @@
@Nullable CancellationSignal cancellationSignal,
@NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Location> consumer) {
LocationRequest currentLocationRequest = new LocationRequest(locationRequest)
- .setNumUpdates(1).setExpireIn(GET_CURRENT_LOCATION_TIMEOUT_MS);
+ .setNumUpdates(1);
+ if (currentLocationRequest.getExpireIn() > GET_CURRENT_LOCATION_MAX_TIMEOUT_MS) {
+ currentLocationRequest.setExpireIn(GET_CURRENT_LOCATION_MAX_TIMEOUT_MS);
+ }
GetCurrentLocationTransport listenerTransport = new GetCurrentLocationTransport(executor,
consumer);
@@ -684,6 +687,7 @@
LocationRequest request = LocationRequest.createFromDeprecatedProvider(
provider, 0, 0, true);
+ request.setExpireIn(GET_CURRENT_LOCATION_MAX_TIMEOUT_MS);
requestLocationUpdates(request, listener, looper);
}
@@ -704,6 +708,7 @@
* @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)}
* instead as it does not carry a risk of extreme battery drain.
*/
+ @Deprecated
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestSingleUpdate(
@NonNull Criteria criteria,
@@ -714,6 +719,7 @@
LocationRequest request = LocationRequest.createFromDeprecatedCriteria(
criteria, 0, 0, true);
+ request.setExpireIn(GET_CURRENT_LOCATION_MAX_TIMEOUT_MS);
requestLocationUpdates(request, listener, looper);
}
@@ -732,6 +738,7 @@
* @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)}
* instead as it does not carry a risk of extreme battery drain.
*/
+ @Deprecated
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestSingleUpdate(@NonNull String provider,
@NonNull PendingIntent pendingIntent) {
@@ -740,6 +747,7 @@
LocationRequest request = LocationRequest.createFromDeprecatedProvider(
provider, 0, 0, true);
+ request.setExpireIn(GET_CURRENT_LOCATION_MAX_TIMEOUT_MS);
requestLocationUpdates(request, pendingIntent);
}
@@ -759,6 +767,7 @@
* @deprecated Use {@link #getCurrentLocation(String, CancellationSignal, Executor, Consumer)}
* instead as it does not carry a risk of extreme battery drain.
*/
+ @Deprecated
@RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
public void requestSingleUpdate(@NonNull Criteria criteria,
@NonNull PendingIntent pendingIntent) {
@@ -767,6 +776,7 @@
LocationRequest request = LocationRequest.createFromDeprecatedCriteria(
criteria, 0, 0, true);
+ request.setExpireIn(GET_CURRENT_LOCATION_MAX_TIMEOUT_MS);
requestLocationUpdates(request, pendingIntent);
}
@@ -1835,7 +1845,7 @@
}
try {
- return mGnssStatusListenerManager.addListener(listener, new Handler());
+ return mGnssStatusListenerManager.addListener(listener, Runnable::run);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2422,7 +2432,7 @@
mAlarmManager = alarmManager;
mAlarmManager.set(
ELAPSED_REALTIME,
- SystemClock.elapsedRealtime() + GET_CURRENT_LOCATION_TIMEOUT_MS,
+ SystemClock.elapsedRealtime() + GET_CURRENT_LOCATION_MAX_TIMEOUT_MS,
"GetCurrentLocation",
this,
null);
@@ -2474,9 +2484,6 @@
}
@Override
- public void onStatusChanged(String provider, int status, Bundle extras) {}
-
- @Override
public void onProviderEnabled(String provider) {}
@Override
@@ -2486,6 +2493,11 @@
deliverResult(null);
}
+ @Override
+ public void onRemoved() {
+ deliverResult(null);
+ }
+
private synchronized void deliverResult(@Nullable Location location) {
if (mExecutor == null) {
return;
@@ -2561,37 +2573,6 @@
}
@Override
- public void onStatusChanged(String provider, int status, Bundle extras) {
- Executor currentExecutor = mExecutor;
- if (currentExecutor == null) {
- return;
- }
-
- try {
- currentExecutor.execute(() -> {
- try {
- if (currentExecutor != mExecutor) {
- return;
- }
-
- // we may be under the binder identity if a direct executor is used
- long identity = Binder.clearCallingIdentity();
- try {
- mListener.onStatusChanged(provider, status, extras);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- } finally {
- locationCallbackFinished();
- }
- });
- } catch (RejectedExecutionException e) {
- locationCallbackFinished();
- throw e;
- }
- }
-
- @Override
public void onProviderEnabled(String provider) {
Executor currentExecutor = mExecutor;
if (currentExecutor == null) {
@@ -2653,6 +2634,14 @@
}
}
+ @Override
+ public void onRemoved() {
+ unregister();
+ synchronized (mListeners) {
+ mListeners.remove(mListener, this);
+ }
+ }
+
private void locationCallbackFinished() {
try {
mService.locationCallbackFinished(this);
@@ -2694,9 +2683,9 @@
return mTtff;
}
- public boolean addListener(@NonNull GpsStatus.Listener listener, @NonNull Handler handler)
+ public boolean addListener(@NonNull GpsStatus.Listener listener, @NonNull Executor executor)
throws RemoteException {
- return addInternal(listener, handler);
+ return addInternal(listener, executor);
}
public boolean addListener(@NonNull OnNmeaMessageListener listener,
@@ -2750,9 +2739,14 @@
protected boolean registerService() throws RemoteException {
Preconditions.checkState(mListenerTransport == null);
- mListenerTransport = new GnssStatusListener();
- return mService.registerGnssStatusCallback(mListenerTransport,
- mContext.getPackageName(), mContext.getFeatureId());
+ GnssStatusListener transport = new GnssStatusListener();
+ if (mService.registerGnssStatusCallback(transport, mContext.getPackageName(),
+ mContext.getFeatureId())) {
+ mListenerTransport = transport;
+ return true;
+ } else {
+ return false;
+ }
}
@Override
@@ -2810,10 +2804,14 @@
protected boolean registerService() throws RemoteException {
Preconditions.checkState(mListenerTransport == null);
- mListenerTransport = new GnssMeasurementsListener();
- return mService.addGnssMeasurementsListener(mListenerTransport,
- mContext.getPackageName(), mContext.getFeatureId(),
- "gnss measurement callback");
+ GnssMeasurementsListener transport = new GnssMeasurementsListener();
+ if (mService.addGnssMeasurementsListener(transport, mContext.getPackageName(),
+ mContext.getFeatureId(), "gnss measurement callback")) {
+ mListenerTransport = transport;
+ return true;
+ } else {
+ return false;
+ }
}
@Override
@@ -2847,10 +2845,14 @@
protected boolean registerService() throws RemoteException {
Preconditions.checkState(mListenerTransport == null);
- mListenerTransport = new GnssNavigationMessageListener();
- return mService.addGnssNavigationMessageListener(mListenerTransport,
- mContext.getPackageName(), mContext.getFeatureId(),
- "gnss navigation callback");
+ GnssNavigationMessageListener transport = new GnssNavigationMessageListener();
+ if (mService.addGnssNavigationMessageListener(transport, mContext.getPackageName(),
+ mContext.getFeatureId(), "gnss navigation callback")) {
+ mListenerTransport = transport;
+ return true;
+ } else {
+ return false;
+ }
}
@Override
@@ -2884,9 +2886,14 @@
protected boolean registerService() throws RemoteException {
Preconditions.checkState(mListenerTransport == null);
- mListenerTransport = new BatchedLocationCallback();
- return mService.addGnssBatchingCallback(mListenerTransport, mContext.getPackageName(),
- mContext.getFeatureId(), "batched location callback");
+ BatchedLocationCallback transport = new BatchedLocationCallback();
+ if (mService.addGnssBatchingCallback(transport, mContext.getPackageName(),
+ mContext.getFeatureId(), "batched location callback")) {
+ mListenerTransport = transport;
+ return true;
+ } else {
+ return false;
+ }
}
@Override
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index 0f38f7f..ca8f2ac 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -161,6 +161,7 @@
private boolean mExplicitFastestInterval = false;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private long mExpireAt = Long.MAX_VALUE; // no expiry
+ private long mExpireIn = Long.MAX_VALUE; // no expiry
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private int mNumUpdates = Integer.MAX_VALUE; // no expiry
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -268,6 +269,7 @@
mFastestInterval = src.mFastestInterval;
mExplicitFastestInterval = src.mExplicitFastestInterval;
mExpireAt = src.mExpireAt;
+ mExpireIn = src.mExpireIn;
mNumUpdates = src.mNumUpdates;
mSmallestDisplacement = src.mSmallestDisplacement;
mProvider = src.mProvider;
@@ -342,7 +344,7 @@
* @throws IllegalArgumentException if the interval is less than zero
*/
public @NonNull LocationRequest setInterval(long millis) {
- checkInterval(millis);
+ Preconditions.checkArgument(millis >= 0, "invalid interval: + millis");
mInterval = millis;
if (!mExplicitFastestInterval) {
mFastestInterval = (long) (mInterval / FASTEST_INTERVAL_FACTOR);
@@ -370,9 +372,7 @@
*
* @param enabled Enable or disable low power mode
* @return the same object, so that setters can be chained
- * @hide
*/
- @SystemApi
public @NonNull LocationRequest setLowPowerMode(boolean enabled) {
mLowPowerMode = enabled;
return this;
@@ -380,10 +380,7 @@
/**
* Returns true if low power mode is enabled.
- *
- * @hide
*/
- @SystemApi
public boolean isLowPowerMode() {
return mLowPowerMode;
}
@@ -431,93 +428,97 @@
* <p>An interval of 0 is allowed, but not recommended, since
* location updates may be extremely fast on future implementations.
*
- * <p>If {@link #setFastestInterval} is set slower than {@link #setInterval},
+ * <p>If the fastest interval set is slower than {@link #setInterval},
* then your effective fastest interval is {@link #setInterval}.
*
- * @param millis fastest interval for updates in milliseconds, exact
+ * @param millis fastest interval for updates in milliseconds
* @return the same object, so that setters can be chained
* @throws IllegalArgumentException if the interval is less than zero
*/
public @NonNull LocationRequest setFastestInterval(long millis) {
- checkInterval(millis);
+ Preconditions.checkArgument(millis >= 0, "invalid interval: + millis");
mExplicitFastestInterval = true;
mFastestInterval = millis;
return this;
}
/**
- * Get the fastest interval of this request, in milliseconds.
+ * Get the fastest interval of this request in milliseconds. The system will never provide
+ * location updates faster than the minimum of the fastest interval and {@link #getInterval}.
*
- * <p>The system will never provide location updates faster
- * than the minimum of {@link #getFastestInterval} and
- * {@link #getInterval}.
- *
- * @return fastest interval in milliseconds, exact
+ * @return fastest interval in milliseconds
*/
public long getFastestInterval() {
return mFastestInterval;
}
/**
- * Set the duration of this request, in milliseconds.
+ * Set the expiration time of this request in milliseconds of realtime since boot. Values in the
+ * past are allowed, but indicate that the request has already expired. The location manager
+ * will automatically stop updates after the request expires.
*
- * <p>The duration begins immediately (and not when the request
- * is passed to the location manager), so call this method again
- * if the request is re-used at a later time.
+ * @param millis expiration time of request in milliseconds since boot
+ * @return the same object, so that setters can be chained
+ * @see SystemClock#elapsedRealtime()
+ * @deprecated Prefer {@link #setExpireIn(long)}.
+ */
+ @Deprecated
+ public @NonNull LocationRequest setExpireAt(long millis) {
+ mExpireAt = Math.max(millis, 0);
+ return this;
+ }
+
+ /**
+ * Get the request expiration time in milliseconds of realtime since boot.
*
- * <p>The location manager will automatically stop updates after
- * the request expires.
- *
- * <p>The duration includes suspend time. Values less than 0
- * are allowed, but indicate that the request has already expired.
+ * @return request expiration time in milliseconds since boot
+ * @see SystemClock#elapsedRealtime()
+ * @deprecated Prefer {@link #getExpireIn()}.
+ */
+ @Deprecated
+ public long getExpireAt() {
+ return mExpireAt;
+ }
+
+ /**
+ * Set the duration of this request in milliseconds of realtime. Values less than 0 are allowed,
+ * but indicate that the request has already expired. The location manager will automatically
+ * stop updates after the request expires.
*
* @param millis duration of request in milliseconds
* @return the same object, so that setters can be chained
+ * @see SystemClock#elapsedRealtime()
*/
public @NonNull LocationRequest setExpireIn(long millis) {
- long elapsedRealtime = SystemClock.elapsedRealtime();
+ mExpireIn = millis;
+ return this;
+ }
+ /**
+ * Get the request expiration duration in milliseconds of realtime.
+ *
+ * @return request expiration duration in milliseconds
+ * @see SystemClock#elapsedRealtime()
+ */
+ public long getExpireIn() {
+ return mExpireIn;
+ }
+
+ /**
+ * Returns the realtime at which this request expires, taking into account both
+ * {@link #setExpireAt(long)} and {@link #setExpireIn(long)} relative to the given realtime.
+ *
+ * @hide
+ */
+ public long getExpirationRealtimeMs(long startRealtimeMs) {
+ long expirationRealtimeMs;
// Check for > Long.MAX_VALUE overflow (elapsedRealtime > 0):
- if (millis > Long.MAX_VALUE - elapsedRealtime) {
- mExpireAt = Long.MAX_VALUE;
+ if (mExpireIn > Long.MAX_VALUE - startRealtimeMs) {
+ expirationRealtimeMs = Long.MAX_VALUE;
} else {
- mExpireAt = millis + elapsedRealtime;
+ expirationRealtimeMs = startRealtimeMs + mExpireIn;
}
-
- if (mExpireAt < 0) mExpireAt = 0;
- return this;
- }
-
- /**
- * Set the request expiration time, in millisecond since boot.
- *
- * <p>This expiration time uses the same time base as {@link SystemClock#elapsedRealtime}.
- *
- * <p>The location manager will automatically stop updates after
- * the request expires.
- *
- * <p>The duration includes suspend time. Values before {@link SystemClock#elapsedRealtime}
- * are allowed, but indicate that the request has already expired.
- *
- * @param millis expiration time of request, in milliseconds since boot including suspend
- * @return the same object, so that setters can be chained
- */
- public @NonNull LocationRequest setExpireAt(long millis) {
- mExpireAt = millis;
- if (mExpireAt < 0) mExpireAt = 0;
- return this;
- }
-
- /**
- * Get the request expiration time, in milliseconds since boot.
- *
- * <p>This value can be compared to {@link SystemClock#elapsedRealtime} to determine
- * the time until expiration.
- *
- * @return expiration time of request, in milliseconds since boot including suspend
- */
- public long getExpireAt() {
- return mExpireAt;
+ return Math.min(expirationRealtimeMs, mExpireAt);
}
/**
@@ -638,13 +639,6 @@
}
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
- private static void checkInterval(long millis) {
- if (millis < 0) {
- throw new IllegalArgumentException("invalid interval: " + millis);
- }
- }
-
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private static void checkQuality(int quality) {
switch (quality) {
case ACCURACY_FINE:
@@ -682,6 +676,7 @@
request.setFastestInterval(in.readLong());
request.setInterval(in.readLong());
request.setExpireAt(in.readLong());
+ request.setExpireIn(in.readLong());
request.setNumUpdates(in.readInt());
request.setSmallestDisplacement(in.readFloat());
request.setHideFromAppOps(in.readInt() != 0);
@@ -711,6 +706,7 @@
parcel.writeLong(mFastestInterval);
parcel.writeLong(mInterval);
parcel.writeLong(mExpireAt);
+ parcel.writeLong(mExpireIn);
parcel.writeInt(mNumUpdates);
parcel.writeFloat(mSmallestDisplacement);
parcel.writeInt(mHideFromAppOps ? 1 : 0);
@@ -753,9 +749,11 @@
s.append(" fastest=");
TimeUtils.formatDuration(mFastestInterval, s);
if (mExpireAt != Long.MAX_VALUE) {
- long expireIn = mExpireAt - SystemClock.elapsedRealtime();
+ s.append(" expireAt=").append(TimeUtils.formatUptime(mExpireAt));
+ }
+ if (mExpireIn != Long.MAX_VALUE) {
s.append(" expireIn=");
- TimeUtils.formatDuration(expireIn, s);
+ TimeUtils.formatDuration(mExpireIn, s);
}
if (mNumUpdates != Integer.MAX_VALUE) {
s.append(" num=").append(mNumUpdates);
diff --git a/location/lib/Android.bp b/location/lib/Android.bp
index fe0f669..cd45e8e 100644
--- a/location/lib/Android.bp
+++ b/location/lib/Android.bp
@@ -17,10 +17,8 @@
java_sdk_library {
name: "com.android.location.provider",
srcs: ["java/**/*.java"],
- api_srcs: [":framework-all-sources"],
libs: [
"androidx.annotation_annotation",
- "framework-all",
],
api_packages: ["com.android.location.provider"],
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index f797da7..9ad7f2a 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -908,6 +908,7 @@
/** @hide */
@UnsupportedAppUsage
+ @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public void setMasterMute(boolean mute, int flags) {
final IAudioService service = getService();
try {
diff --git a/media/java/android/media/IMediaRouter2Client.aidl b/media/java/android/media/IMediaRouter2Client.aidl
index 26184af..72c33f99 100644
--- a/media/java/android/media/IMediaRouter2Client.aidl
+++ b/media/java/android/media/IMediaRouter2Client.aidl
@@ -16,12 +16,14 @@
package android.media;
-import android.media.MediaRoute2ProviderInfo;
+import android.media.MediaRoute2Info;
/**
* @hide
*/
oneway interface IMediaRouter2Client {
void notifyRestoreRoute();
- void notifyProviderInfosUpdated(in List<MediaRoute2ProviderInfo> providers);
+ void notifyRoutesAdded(in List<MediaRoute2Info> routes);
+ void notifyRoutesRemoved(in List<MediaRoute2Info> routes);
+ void notifyRoutesChanged(in List<MediaRoute2Info> routes);
}
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 70a343f..7ba122b 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -395,7 +395,7 @@
* <p>The row stride for this color plane, in bytes.</p>
*
* <p>This is the distance between the start of two consecutive rows of
- * pixels in the image. Note that row stried is undefined for some formats
+ * pixels in the image. Note that row stride is undefined for some formats
* such as
* {@link android.graphics.ImageFormat#RAW_PRIVATE RAW_PRIVATE},
* and calling getRowStride on images of these formats will
diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java
index f813d1b..7bc2b31 100644
--- a/media/java/android/media/ImageWriter.java
+++ b/media/java/android/media/ImageWriter.java
@@ -192,13 +192,15 @@
mMaxImages = maxImages;
- if (format == ImageFormat.UNKNOWN) {
- format = SurfaceUtils.getSurfaceFormat(surface);
- }
// Note that the underlying BufferQueue is working in synchronous mode
// to avoid dropping any buffers.
mNativeContext = nativeInit(new WeakReference<>(this), surface, maxImages, format);
+ // nativeInit internally overrides UNKNOWN format. So does surface format query after
+ // nativeInit and before getEstimatedNativeAllocBytes().
+ if (format == ImageFormat.UNKNOWN) {
+ format = SurfaceUtils.getSurfaceFormat(surface);
+ }
// Estimate the native buffer allocation size and register it so it gets accounted for
// during GC. Note that this doesn't include the buffers required by the buffer queue
// itself and the buffers requested by the producer.
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index cc5ddeb..5d2bdd7 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -34,6 +34,7 @@
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -62,7 +63,8 @@
* method before the rest of the methods in this class. This method may be
* time-consuming.
*
- * @param path The path of the input media file.
+ * @param path The path, or the URI (doesn't support streaming source currently)
+ * of the input media file.
* @throws IllegalArgumentException If the path is invalid.
*/
public void setDataSource(String path) throws IllegalArgumentException {
@@ -70,6 +72,15 @@
throw new IllegalArgumentException("null path");
}
+ final Uri uri = Uri.parse(path);
+ final String scheme = uri.getScheme();
+ if ("file".equals(scheme)) {
+ path = uri.getPath();
+ } else if (scheme != null) {
+ setDataSource(path, new HashMap<String, String>());
+ return;
+ }
+
try (FileInputStream is = new FileInputStream(path)) {
FileDescriptor fd = is.getFD();
setDataSource(fd, 0, 0x7ffffffffffffffL);
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 59bd96f..457ccb7 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -314,7 +314,7 @@
List<String> mSupportedCategories;
int mVolume;
int mVolumeMax;
- int mVolumeHandling;
+ int mVolumeHandling = PLAYBACK_VOLUME_FIXED;
Bundle mExtras;
public Builder(@NonNull String id, @NonNull String name) {
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index b52e2d6..ce18ab3 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -33,7 +33,9 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
@@ -51,23 +53,23 @@
@GuardedBy("sLock")
private static MediaRouter2 sInstance;
- private Context mContext;
+ private final Context mContext;
private final IMediaRouterService mMediaRouterService;
private final CopyOnWriteArrayList<CallbackRecord> mCallbackRecords =
new CopyOnWriteArrayList<>();
- @GuardedBy("sLock")
- private List<String> mControlCategories = Collections.emptyList();
+
+ private final String mPackageName;
+ private final Map<String, MediaRoute2Info> mRoutes = new HashMap<>();
+
+ private volatile List<String> mControlCategories = Collections.emptyList();
+
+ private MediaRoute2Info mSelectedRoute;
@GuardedBy("sLock")
private Client mClient;
- private final String mPackageName;
final Handler mHandler;
-
- List<MediaRoute2ProviderInfo> mProviders = Collections.emptyList();
- volatile List<MediaRoute2Info> mRoutes = Collections.emptyList();
-
- MediaRoute2Info mSelectedRoute;
+ volatile List<MediaRoute2Info> mFilteredRoutes = Collections.emptyList();
/**
* Gets an instance of the media router associated with the context.
@@ -137,6 +139,7 @@
}
}
}
+ //TODO: Is it thread-safe?
record.notifyRoutes();
//TODO: Update discovery request here.
@@ -181,31 +184,22 @@
public void setControlCategories(@NonNull Collection<String> controlCategories) {
Objects.requireNonNull(controlCategories, "control categories must not be null");
- Client client;
- List<String> newControlCategories = new ArrayList<>(controlCategories);
- synchronized (sLock) {
- mControlCategories = newControlCategories;
- client = mClient;
- }
- if (client != null) {
- try {
- mMediaRouterService.setControlCategories2(client, newControlCategories);
- } catch (RemoteException ex) {
- Log.e(TAG, "Unable to set control categories.", ex);
- }
- }
- mHandler.sendMessage(obtainMessage(MediaRouter2::refreshAndNotifyRoutes, this));
+ // To ensure invoking callbacks correctly according to control categories
+ mHandler.sendMessage(obtainMessage(MediaRouter2::setControlCategoriesOnHandler,
+ MediaRouter2.this, new ArrayList<>(controlCategories)));
}
+
/**
- * Gets the list of {@link MediaRoute2Info routes} currently known to the media router.
+ * Gets the unmodifiable list of {@link MediaRoute2Info routes} currently
+ * known to the media router.
*
* @return the list of routes that support at least one of the control categories set by
* the application
*/
@NonNull
public List<MediaRoute2Info> getRoutes() {
- return mRoutes;
+ return mFilteredRoutes;
}
/**
@@ -326,102 +320,145 @@
return -1;
}
- void onProviderInfosUpdated(List<MediaRoute2ProviderInfo> providers) {
- if (providers == null) {
- Log.w(TAG, "Providers info is null.");
- return;
- }
+ private void setControlCategoriesOnHandler(List<String> newControlCategories) {
+ List<String> prevControlCategories = mControlCategories;
+ List<MediaRoute2Info> addedRoutes = new ArrayList<>();
+ List<MediaRoute2Info> removedRoutes = new ArrayList<>();
+ List<MediaRoute2Info> filteredRoutes = new ArrayList<>();
- mProviders = providers;
- refreshAndNotifyRoutes();
- }
-
- void refreshAndNotifyRoutes() {
- ArrayList<MediaRoute2Info> routes = new ArrayList<>();
-
- List<String> controlCategories;
+ mControlCategories = newControlCategories;
+ Client client;
synchronized (sLock) {
- controlCategories = mControlCategories;
+ client = mClient;
+ }
+ if (client != null) {
+ try {
+ mMediaRouterService.setControlCategories2(client, mControlCategories);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Unable to set control categories.", ex);
+ }
}
- for (MediaRoute2ProviderInfo provider : mProviders) {
- updateProvider(provider, controlCategories, routes);
+ for (MediaRoute2Info route : mRoutes.values()) {
+ boolean preSupported = route.supportsControlCategory(prevControlCategories);
+ boolean postSupported = route.supportsControlCategory(newControlCategories);
+ if (postSupported) {
+ filteredRoutes.add(route);
+ }
+ if (preSupported == postSupported) {
+ continue;
+ }
+ if (preSupported) {
+ removedRoutes.add(route);
+ } else {
+ addedRoutes.add(route);
+ }
}
+ mFilteredRoutes = Collections.unmodifiableList(filteredRoutes);
- //TODO: Can orders be changed?
- if (!Objects.equals(mRoutes, routes)) {
- mRoutes = Collections.unmodifiableList(routes);
- notifyRouteListChanged(mRoutes);
+ if (removedRoutes.size() > 0) {
+ notifyRoutesRemoved(removedRoutes);
+ }
+ if (addedRoutes.size() > 0) {
+ notifyRoutesAdded(addedRoutes);
}
}
- void updateProvider(MediaRoute2ProviderInfo provider, List<String> controlCategories,
- List<MediaRoute2Info> outRoutes) {
- if (provider == null || !provider.isValid()) {
- Log.w(TAG, "Ignoring invalid provider : " + provider);
- return;
- }
-
- final Collection<MediaRoute2Info> routes = provider.getRoutes();
+ void addRoutesOnHandler(List<MediaRoute2Info> routes) {
+ List<MediaRoute2Info> addedRoutes = new ArrayList<>();
for (MediaRoute2Info route : routes) {
- if (!route.isValid()) {
- Log.w(TAG, "Ignoring invalid route : " + route);
- continue;
+ mRoutes.put(route.getUniqueId(), route);
+ if (route.supportsControlCategory(mControlCategories)) {
+ addedRoutes.add(route);
}
- if (!route.supportsControlCategory(controlCategories)) {
- continue;
- }
- MediaRoute2Info preRoute = findRouteById(route.getId());
- if (!route.equals(preRoute)) {
- notifyRouteChanged(route);
- }
- outRoutes.add(route);
+ }
+ if (addedRoutes.size() > 0) {
+ refreshFilteredRoutes();
+ notifyRoutesAdded(addedRoutes);
}
}
- MediaRoute2Info findRouteById(String id) {
- for (MediaRoute2Info route : mRoutes) {
- if (route.getId().equals(id)) return route;
+ void removeRoutesOnHandler(List<MediaRoute2Info> routes) {
+ List<MediaRoute2Info> removedRoutes = new ArrayList<>();
+ for (MediaRoute2Info route : routes) {
+ mRoutes.remove(route.getUniqueId());
+ if (route.supportsControlCategory(mControlCategories)) {
+ removedRoutes.add(route);
+ }
}
- return null;
+ if (removedRoutes.size() > 0) {
+ refreshFilteredRoutes();
+ notifyRoutesRemoved(removedRoutes);
+ }
}
- void notifyRouteListChanged(List<MediaRoute2Info> routes) {
+ void changeRoutesOnHandler(List<MediaRoute2Info> routes) {
+ List<MediaRoute2Info> changedRoutes = new ArrayList<>();
+ for (MediaRoute2Info route : routes) {
+ mRoutes.put(route.getUniqueId(), route);
+ if (route.supportsControlCategory(mControlCategories)) {
+ changedRoutes.add(route);
+ }
+ }
+ if (changedRoutes.size() > 0) {
+ refreshFilteredRoutes();
+ notifyRoutesChanged(changedRoutes);
+ }
+ }
+
+ private void refreshFilteredRoutes() {
+ List<MediaRoute2Info> filteredRoutes = new ArrayList<>();
+
+ for (MediaRoute2Info route : mRoutes.values()) {
+ if (route.supportsControlCategory(mControlCategories)) {
+ filteredRoutes.add(route);
+ }
+ }
+ mFilteredRoutes = Collections.unmodifiableList(filteredRoutes);
+ }
+
+ private void notifyRoutesAdded(List<MediaRoute2Info> routes) {
+ for (CallbackRecord record: mCallbackRecords) {
+ record.mExecutor.execute(
+ () -> record.mCallback.onRoutesAdded(routes));
+ }
+ }
+
+ private void notifyRoutesRemoved(List<MediaRoute2Info> routes) {
+ for (CallbackRecord record: mCallbackRecords) {
+ record.mExecutor.execute(
+ () -> record.mCallback.onRoutesRemoved(routes));
+ }
+ }
+
+ private void notifyRoutesChanged(List<MediaRoute2Info> routes) {
for (CallbackRecord record: mCallbackRecords) {
record.mExecutor.execute(
() -> record.mCallback.onRoutesChanged(routes));
}
}
- void notifyRouteChanged(MediaRoute2Info route) {
- for (CallbackRecord record: mCallbackRecords) {
- record.mExecutor.execute(
- () -> record.mCallback.onRouteChanged(route));
- }
- }
-
/**
* Interface for receiving events about media routing changes.
*/
public static class Callback {
//TODO: clean up these callbacks
- /**
- * Called when a route is added.
- */
- public void onRouteAdded(MediaRoute2Info routeInfo) {}
/**
- * Called when a route is changed.
+ * Called when routes are added.
+ * @param routes the list of routes that have been added. It's never empty.
*/
- public void onRouteChanged(MediaRoute2Info routeInfo) {}
+ public void onRoutesAdded(@NonNull List<MediaRoute2Info> routes) {}
/**
- * Called when a route is removed.
+ * Called when routes are removed.
+ * @param routes the list of routes that have been removed. It's never empty.
*/
- public void onRouteRemoved(MediaRoute2Info routeInfo) {}
+ public void onRoutesRemoved(@NonNull List<MediaRoute2Info> routes) {}
/**
- * Called when the list of routes is changed.
+ * Called when routes are changed.
+ * @param routes the list of routes that have been changed. It's never empty.
*/
public void onRoutesChanged(@NonNull List<MediaRoute2Info> routes) {}
}
@@ -436,11 +473,10 @@
}
void notifyRoutes() {
- final List<MediaRoute2Info> routes = mRoutes;
+ final List<MediaRoute2Info> routes = mFilteredRoutes;
// notify only when bound to media router service.
- //TODO: Correct the condition when control category, default route, .. are finalized.
if (routes.size() > 0) {
- mExecutor.execute(() -> mCallback.onRoutesChanged(routes));
+ mExecutor.execute(() -> mCallback.onRoutesAdded(routes));
}
}
}
@@ -450,9 +486,21 @@
public void notifyRestoreRoute() throws RemoteException {}
@Override
- public void notifyProviderInfosUpdated(List<MediaRoute2ProviderInfo> info) {
- mHandler.sendMessage(obtainMessage(MediaRouter2::onProviderInfosUpdated,
- MediaRouter2.this, info));
+ public void notifyRoutesAdded(List<MediaRoute2Info> routes) {
+ mHandler.sendMessage(obtainMessage(MediaRouter2::addRoutesOnHandler,
+ MediaRouter2.this, routes));
+ }
+
+ @Override
+ public void notifyRoutesRemoved(List<MediaRoute2Info> routes) {
+ mHandler.sendMessage(obtainMessage(MediaRouter2::removeRoutesOnHandler,
+ MediaRouter2.this, routes));
+ }
+
+ @Override
+ public void notifyRoutesChanged(List<MediaRoute2Info> routes) {
+ mHandler.sendMessage(obtainMessage(MediaRouter2::changeRoutesOnHandler,
+ MediaRouter2.this, routes));
}
}
}
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 0d7b6ff..7e848a0 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -67,7 +67,7 @@
@NonNull
List<MediaRoute2Info> mRoutes = Collections.emptyList();
@NonNull
- ConcurrentMap<String, List<String>> mControlCategoryMap = new ConcurrentHashMap<>();
+ final ConcurrentMap<String, List<String>> mControlCategoryMap = new ConcurrentHashMap<>();
/**
* Gets an instance of media router manager that controls media route of other applications.
@@ -427,6 +427,8 @@
* A client may refresh available routes for each application.
*/
public void onRoutesChanged(@NonNull List<MediaRoute2Info> routes) {}
+
+ //TODO: add onControlCategoriesChanged to notify available routes are changed
}
final class CallbackRecord {
diff --git a/media/java/android/media/Utils.java b/media/java/android/media/Utils.java
index 5b62f16..d942bb6 100644
--- a/media/java/android/media/Utils.java
+++ b/media/java/android/media/Utils.java
@@ -16,8 +16,8 @@
package android.media;
-import android.content.Context;
import android.content.ContentResolver;
+import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
@@ -206,12 +206,13 @@
}
static Size parseSize(Object o, Size fallback) {
+ if (o == null) {
+ return fallback;
+ }
try {
return Size.parseSize((String) o);
} catch (ClassCastException e) {
} catch (NumberFormatException e) {
- } catch (NullPointerException e) {
- return fallback;
}
Log.w(TAG, "could not parse size '" + o + "'");
return fallback;
@@ -226,14 +227,15 @@
return Integer.parseInt(s);
} catch (ClassCastException e) {
} catch (NumberFormatException e) {
- } catch (NullPointerException e) {
- return fallback;
}
Log.w(TAG, "could not parse integer '" + o + "'");
return fallback;
}
static Range<Integer> parseIntRange(Object o, Range<Integer> fallback) {
+ if (o == null) {
+ return fallback;
+ }
try {
String s = (String)o;
int ix = s.indexOf('-');
@@ -246,8 +248,6 @@
return Range.create(value, value);
} catch (ClassCastException e) {
} catch (NumberFormatException e) {
- } catch (NullPointerException e) {
- return fallback;
} catch (IllegalArgumentException e) {
}
Log.w(TAG, "could not parse integer range '" + o + "'");
@@ -255,6 +255,9 @@
}
static Range<Long> parseLongRange(Object o, Range<Long> fallback) {
+ if (o == null) {
+ return fallback;
+ }
try {
String s = (String)o;
int ix = s.indexOf('-');
@@ -267,8 +270,6 @@
return Range.create(value, value);
} catch (ClassCastException e) {
} catch (NumberFormatException e) {
- } catch (NullPointerException e) {
- return fallback;
} catch (IllegalArgumentException e) {
}
Log.w(TAG, "could not parse long range '" + o + "'");
@@ -276,6 +277,9 @@
}
static Range<Rational> parseRationalRange(Object o, Range<Rational> fallback) {
+ if (o == null) {
+ return fallback;
+ }
try {
String s = (String)o;
int ix = s.indexOf('-');
@@ -288,8 +292,6 @@
return Range.create(value, value);
} catch (ClassCastException e) {
} catch (NumberFormatException e) {
- } catch (NullPointerException e) {
- return fallback;
} catch (IllegalArgumentException e) {
}
Log.w(TAG, "could not parse rational range '" + o + "'");
@@ -297,6 +299,9 @@
}
static Pair<Size, Size> parseSizeRange(Object o) {
+ if (o == null) {
+ return null;
+ }
try {
String s = (String)o;
int ix = s.indexOf('-');
@@ -309,8 +314,6 @@
return Pair.create(value, value);
} catch (ClassCastException e) {
} catch (NumberFormatException e) {
- } catch (NullPointerException e) {
- return null;
} catch (IllegalArgumentException e) {
}
Log.w(TAG, "could not parse size range '" + o + "'");
diff --git a/media/java/android/media/tv/OWNER b/media/java/android/media/tv/OWNER
new file mode 100644
index 0000000..64c0bb5
--- /dev/null
+++ b/media/java/android/media/tv/OWNER
@@ -0,0 +1,5 @@
+amyjojo@google.com
+nchalko@google.com
+shubang@google.com
+quxiangfang@google.com
+
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 0228dc9..4ed8f42 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -16,6 +16,13 @@
package android.media.tv.tuner;
+import android.annotation.Nullable;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+import java.util.List;
+
/**
* Tuner is used to interact with tuner devices.
*
@@ -25,11 +32,17 @@
private static final String TAG = "MediaTvTuner";
private static final boolean DEBUG = false;
+ private static final int MSG_ON_FRONTEND_EVENT = 1;
+
static {
System.loadLibrary("media_tv_tuner");
nativeInit();
}
+ private List<Integer> mFrontendIds;
+ private Frontend mFrontend;
+ private EventHandler mHandler;
+
public Tuner() {
nativeSetup();
}
@@ -48,4 +61,123 @@
* Native setup.
*/
private native void nativeSetup();
+
+ /**
+ * Native method to get all frontend IDs.
+ */
+ private native List<Integer> nativeGetFrontendIds();
+
+ /**
+ * Native method to open frontend of the given ID.
+ */
+ private native Frontend nativeOpenFrontendById(int id);
+
+ private native Filter nativeOpenFilter(int type, int subType, int bufferSize);
+
+
+ /**
+ * Frontend Callback.
+ */
+ public interface FrontendCallback {
+
+ /**
+ * Invoked when there is a frontend event.
+ */
+ void onEvent(int frontendEventType);
+ }
+
+ @Nullable
+ private EventHandler createEventHandler() {
+ Looper looper;
+ if ((looper = Looper.myLooper()) != null) {
+ return new EventHandler(looper);
+ } else if ((looper = Looper.getMainLooper()) != null) {
+ return new EventHandler(looper);
+ }
+ return null;
+ }
+
+ private class EventHandler extends Handler {
+ private EventHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_ON_FRONTEND_EVENT:
+ if (mFrontend != null && mFrontend.mCallback != null) {
+ mFrontend.mCallback.onEvent(msg.arg1);
+ }
+ break;
+ default:
+ // fall through
+ }
+ }
+ }
+
+ protected class Frontend {
+ private int mId;
+ private FrontendCallback mCallback;
+
+ private Frontend(int id) {
+ mId = id;
+ }
+
+ public void setCallback(@Nullable FrontendCallback callback, @Nullable Handler handler) {
+ mCallback = callback;
+
+ if (mCallback == null) {
+ return;
+ }
+
+ if (handler == null) {
+ // use default looper if handler is null
+ if (mHandler == null) {
+ mHandler = createEventHandler();
+ }
+ return;
+ }
+
+ Looper looper = handler.getLooper();
+ if (mHandler != null && mHandler.getLooper() == looper) {
+ // the same looper. reuse mHandler
+ return;
+ }
+ mHandler = new EventHandler(looper);
+ }
+ }
+
+ private List<Integer> getFrontendIds() {
+ mFrontendIds = nativeGetFrontendIds();
+ return mFrontendIds;
+ }
+
+ private Frontend openFrontendById(int id) {
+ if (mFrontendIds == null) {
+ mFrontendIds = getFrontendIds();
+ }
+ if (!mFrontendIds.contains(id)) {
+ return null;
+ }
+ mFrontend = nativeOpenFrontendById(id);
+ return mFrontend;
+ }
+
+ private void onFrontendEvent(int eventType) {
+ if (mHandler != null) {
+ mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_FRONTEND_EVENT, eventType, 0));
+ }
+ }
+
+ protected class Filter {
+ int mId;
+ private Filter(int id) {
+ mId = id;
+ }
+ }
+
+ private Filter openFilter(int type, int subType, int bufferSize) {
+ return nativeOpenFilter(type, subType, bufferSize);
+ }
}
diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java
new file mode 100644
index 0000000..411882e
--- /dev/null
+++ b/media/java/android/media/tv/tuner/TunerConstants.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner;
+
+import android.annotation.IntDef;
+import android.hardware.tv.tuner.V1_0.Constants;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * @hide
+ */
+final class TunerConstants {
+ public static final int INVALID_TS_PID = Constants.Constant.INVALID_TS_PID;
+ public static final int INVALID_STREAM_ID = Constants.Constant.INVALID_STREAM_ID;
+
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({FRONTEND_TYPE_UNDEFINED, FRONTEND_TYPE_ANALOG, FRONTEND_TYPE_ATSC, FRONTEND_TYPE_ATSC3,
+ FRONTEND_TYPE_DVBC, FRONTEND_TYPE_DVBS, FRONTEND_TYPE_DVBT, FRONTEND_TYPE_ISDBS,
+ FRONTEND_TYPE_ISDBS3, FRONTEND_TYPE_ISDBT})
+ public @interface FrontendType {}
+
+ public static final int FRONTEND_TYPE_UNDEFINED = Constants.FrontendType.UNDEFINED;
+ public static final int FRONTEND_TYPE_ANALOG = Constants.FrontendType.ANALOG;
+ public static final int FRONTEND_TYPE_ATSC = Constants.FrontendType.ATSC;
+ public static final int FRONTEND_TYPE_ATSC3 = Constants.FrontendType.ATSC3;
+ public static final int FRONTEND_TYPE_DVBC = Constants.FrontendType.DVBC;
+ public static final int FRONTEND_TYPE_DVBS = Constants.FrontendType.DVBS;
+ public static final int FRONTEND_TYPE_DVBT = Constants.FrontendType.DVBT;
+ public static final int FRONTEND_TYPE_ISDBS = Constants.FrontendType.ISDBS;
+ public static final int FRONTEND_TYPE_ISDBS3 = Constants.FrontendType.ISDBS3;
+ public static final int FRONTEND_TYPE_ISDBT = Constants.FrontendType.ISDBT;
+
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({FRONTEND_EVENT_TYPE_LOCKED, FRONTEND_EVENT_TYPE_NO_SIGNAL,
+ FRONTEND_EVENT_TYPE_LOST_LOCK})
+ public @interface FrontendEventType {}
+
+ public static final int FRONTEND_EVENT_TYPE_LOCKED = Constants.FrontendEventType.LOCKED;
+ public static final int FRONTEND_EVENT_TYPE_NO_SIGNAL = Constants.FrontendEventType.NO_SIGNAL;
+ public static final int FRONTEND_EVENT_TYPE_LOST_LOCK = Constants.FrontendEventType.LOST_LOCK;
+
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({DATA_FORMAT_TS, DATA_FORMAT_PES, DATA_FORMAT_ES, DATA_FORMAT_SHV_TLV})
+ public @interface DataFormat {}
+
+ public static final int DATA_FORMAT_TS = Constants.DataFormat.TS;
+ public static final int DATA_FORMAT_PES = Constants.DataFormat.PES;
+ public static final int DATA_FORMAT_ES = Constants.DataFormat.ES;
+ public static final int DATA_FORMAT_SHV_TLV = Constants.DataFormat.SHV_TLV;
+
+ private TunerConstants() {
+ }
+}
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index a596d89..2f53cbb 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -99,13 +99,14 @@
"android_media_Utils.cpp",
],
+ header_libs: [
+ "libgui_headers",
+ ],
+
shared_libs: [
"liblog",
- "libgui",
- "libnativewindow",
"libui",
"libutils",
- "android.hidl.token@1.0-utils",
],
include_dirs: [
@@ -132,6 +133,7 @@
shared_libs: [
"android.hardware.tv.tuner@1.0",
"libandroid_runtime",
+ "libhidlbase",
"liblog",
"libutils",
],
diff --git a/media/jni/android_media_MediaCrypto.cpp b/media/jni/android_media_MediaCrypto.cpp
index 2d9051f..517672e 100644
--- a/media/jni/android_media_MediaCrypto.cpp
+++ b/media/jni/android_media_MediaCrypto.cpp
@@ -24,11 +24,10 @@
#include "jni.h"
#include <nativehelper/JNIHelp.h>
-#include <binder/IServiceManager.h>
#include <cutils/properties.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <mediadrm/DrmUtils.h>
#include <mediadrm/ICrypto.h>
-#include <mediadrm/IMediaDrmService.h>
namespace android {
@@ -64,20 +63,7 @@
// static
sp<ICrypto> JCrypto::MakeCrypto() {
- sp<IServiceManager> sm = defaultServiceManager();
-
- sp<IBinder> binder = sm->getService(String16("media.drm"));
- sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
- if (service == NULL) {
- return NULL;
- }
-
- sp<ICrypto> crypto = service->makeCrypto();
- if (crypto == NULL || (crypto->initCheck() != OK && crypto->initCheck() != NO_INIT)) {
- return NULL;
- }
-
- return crypto;
+ return DrmUtils::MakeCrypto();
}
// static
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index f412161..8f844d4 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -27,14 +27,13 @@
#include "jni.h"
#include <nativehelper/JNIHelp.h>
-#include <binder/IServiceManager.h>
#include <binder/Parcel.h>
#include <binder/PersistableBundle.h>
#include <cutils/properties.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaErrors.h>
+#include <mediadrm/DrmUtils.h>
#include <mediadrm/IDrm.h>
-#include <mediadrm/IMediaDrmService.h>
using ::android::os::PersistableBundle;
@@ -486,20 +485,7 @@
// static
sp<IDrm> JDrm::MakeDrm() {
- sp<IServiceManager> sm = defaultServiceManager();
-
- sp<IBinder> binder = sm->getService(String16("media.drm"));
- sp<IMediaDrmService> service = interface_cast<IMediaDrmService>(binder);
- if (service == NULL) {
- return NULL;
- }
-
- sp<IDrm> drm = service->makeDrm();
- if (drm == NULL || (drm->initCheck() != OK && drm->initCheck() != NO_INIT)) {
- return NULL;
- }
-
- return drm;
+ return DrmUtils::MakeDrm();
}
// static
@@ -537,6 +523,40 @@
}
}
+void JDrm::sendEvent(
+ DrmPlugin::EventType eventType,
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ const hardware::hidl_vec<uint8_t> &data) {
+ Parcel obj;
+ DrmUtils::WriteByteArray(obj, sessionId);
+ DrmUtils::WriteByteArray(obj, data);
+ notify(eventType, 0, &obj);
+}
+
+void JDrm::sendExpirationUpdate(
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ int64_t expiryTimeInMS) {
+ Parcel obj;
+ DrmUtils::WriteExpirationUpdateToParcel(obj, sessionId, expiryTimeInMS);
+ notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
+}
+
+void JDrm::sendKeysChange(
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ const std::vector<DrmKeyStatus> &keyStatusList,
+ bool hasNewUsableKey) {
+ Parcel obj;
+ DrmUtils::WriteKeysChange(obj, sessionId, keyStatusList, hasNewUsableKey);
+ notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
+}
+
+void JDrm::sendSessionLostState(
+ const hardware::hidl_vec<uint8_t> &sessionId) {
+ Parcel obj;
+ DrmUtils::WriteByteArray(obj, sessionId);
+ notify(DrmPlugin::kDrmPluginEventSessionLostState, 0, &obj);
+}
+
void JDrm::disconnect() {
if (mDrm != NULL) {
mDrm->destroyPlugin();
diff --git a/media/jni/android_media_MediaDrm.h b/media/jni/android_media_MediaDrm.h
index 684069b..37d9e07 100644
--- a/media/jni/android_media_MediaDrm.h
+++ b/media/jni/android_media_MediaDrm.h
@@ -21,6 +21,8 @@
#include <media/stagefright/foundation/ABase.h>
#include <mediadrm/IDrm.h>
+#include <mediadrm/IDrmClient.h>
+#include <hidl/HidlSupport.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
@@ -44,7 +46,23 @@
status_t initCheck() const;
sp<IDrm> getDrm() { return mDrm; }
- void notify(DrmPlugin::EventType, int extra, const Parcel *obj);
+ void sendEvent(
+ DrmPlugin::EventType eventType,
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ const hardware::hidl_vec<uint8_t> &data) override;
+
+ void sendExpirationUpdate(
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ int64_t expiryTimeInMS) override;
+
+ void sendKeysChange(
+ const hardware::hidl_vec<uint8_t> &sessionId,
+ const std::vector<DrmKeyStatus> &keyStatusList,
+ bool hasNewUsableKey) override;
+
+ void sendSessionLostState(
+ const hardware::hidl_vec<uint8_t> &sessionId) override;
+
status_t setListener(const sp<DrmListener>& listener);
void disconnect();
@@ -63,6 +81,8 @@
static sp<IDrm> MakeDrm();
static sp<IDrm> MakeDrm(const uint8_t uuid[16], const String8 &appPackageName);
+ void notify(DrmPlugin::EventType, int extra, const Parcel *obj);
+
DISALLOW_EVIL_CONSTRUCTORS(JDrm);
};
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index d499eee..f815097 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -25,15 +25,59 @@
#pragma GCC diagnostic ignored "-Wunused-function"
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using ::android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
using ::android::hardware::tv::tuner::V1_0::ITuner;
+using ::android::hardware::tv::tuner::V1_0::Result;
struct fields_t {
jfieldID context;
+ jmethodID frontendInitID;
+ jmethodID filterInitID;
+ jmethodID onFrontendEventID;
};
static fields_t gFields;
namespace android {
+/////////////// FilterCallback ///////////////////////
+//TODO: implement filter callback
+Return<void> FilterCallback::onFilterEvent(const DemuxFilterEvent& /* filterEvent */) {
+ ALOGD("FilterCallback::onFilterEvent");
+ return Void();
+}
+Return<void> FilterCallback::onFilterStatus(const DemuxFilterStatus /*status*/) {
+ ALOGD("FilterCallback::onFilterStatu");
+ return Void();
+}
+
+/////////////// FrontendCallback ///////////////////////
+
+FrontendCallback::FrontendCallback(jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {}
+
+Return<void> FrontendCallback::onEvent(FrontendEventType frontendEventType) {
+ ALOGD("FrontendCallback::onEvent, type=%d", frontendEventType);
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ env->CallVoidMethod(
+ mObject,
+ gFields.onFrontendEventID,
+ (jint)frontendEventType);
+ return Void();
+}
+Return<void> FrontendCallback::onDiseqcMessage(const hidl_vec<uint8_t>& /*diseqcMessage*/) {
+ ALOGD("FrontendCallback::onDiseqcMessage");
+ return Void();
+}
+
+Return<void> FrontendCallback::onScanMessage(
+ FrontendScanMessageType type, const FrontendScanMessage& /*message*/) {
+ ALOGD("FrontendCallback::onScanMessage, type=%d", type);
+ return Void();
+}
+
+/////////////// Tuner ///////////////////////
sp<ITuner> JTuner::mTuner;
@@ -69,6 +113,102 @@
return mTuner;
}
+jobject JTuner::getFrontendIds() {
+ ALOGD("JTuner::getFrontendIds()");
+ mTuner->getFrontendIds([&](Result, const hidl_vec<FrontendId>& frontendIds) {
+ mFeIds = frontendIds;
+ });
+ if (mFeIds.size() == 0) {
+ ALOGW("Frontend isn't available");
+ return NULL;
+ }
+
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ jclass arrayListClazz = env->FindClass("java/util/ArrayList");
+ jmethodID arrayListAdd = env->GetMethodID(arrayListClazz, "add", "(Ljava/lang/Object;)Z");
+ jobject obj = env->NewObject(arrayListClazz, env->GetMethodID(arrayListClazz, "<init>", "()V"));
+
+ jclass integerClazz = env->FindClass("java/lang/Integer");
+ jmethodID intInit = env->GetMethodID(integerClazz, "<init>", "(I)V");
+
+ for (int i=0; i < mFeIds.size(); i++) {
+ jobject idObj = env->NewObject(integerClazz, intInit, mFeIds[i]);
+ env->CallBooleanMethod(obj, arrayListAdd, idObj);
+ }
+ return obj;
+}
+
+jobject JTuner::openFrontendById(int id) {
+ sp<IFrontend> fe;
+ mTuner->openFrontendById(id, [&](Result, const sp<IFrontend>& frontend) {
+ fe = frontend;
+ });
+ if (fe == nullptr) {
+ ALOGE("Failed to open frontend");
+ return NULL;
+ }
+ mFe = fe;
+ sp<FrontendCallback> feCb = new FrontendCallback(mObject, id);
+ fe->setCallback(feCb);
+
+ jint jId = (jint) id;
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ // TODO: add more fields to frontend
+ return env->NewObject(
+ env->FindClass("android/media/tv/tuner/Tuner$Frontend"),
+ gFields.frontendInitID,
+ mObject,
+ (jint) jId);
+}
+
+bool JTuner::openDemux() {
+ if (mTuner == nullptr) {
+ return false;
+ }
+ if (mDemux != nullptr) {
+ return true;
+ }
+ mTuner->openDemux([&](Result, uint32_t demuxId, const sp<IDemux>& demux) {
+ mDemux = demux;
+ mDemuxId = demuxId;
+ ALOGD("open demux, id = %d", demuxId);
+ });
+ if (mDemux == nullptr) {
+ return false;
+ }
+ return true;
+}
+
+jobject JTuner::openFilter(DemuxFilterType type, int bufferSize) {
+ if (mDemux == NULL) {
+ if (!openDemux()) {
+ return NULL;
+ }
+ }
+
+ sp<IFilter> f;
+ mDemux->openFilter(type, bufferSize, new FilterCallback,
+ [&](Result, const sp<IFilter>& filter) {
+ f = filter;
+ });
+ if (f == NULL) {
+ ALOGD("Failed to open filter, type = %d", type.mainType);
+ return NULL;
+ }
+ int fId;
+ f->getId([&](Result, uint32_t filterId) {
+ fId = filterId;
+ });
+ mFilters[fId] = f;
+
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ return env->NewObject(
+ env->FindClass("android/media/tv/tuner/Tuner$Filter"),
+ gFields.filterInitID,
+ mObject,
+ (jint) fId);
+}
+
} // namespace android
////////////////////////////////////////////////////////////////////////////////
@@ -99,6 +239,16 @@
gFields.context = env->GetFieldID(clazz, "mNativeContext", "J");
CHECK(gFields.context != NULL);
+
+ gFields.onFrontendEventID = env->GetMethodID(clazz, "onFrontendEvent", "(I)V");
+
+ jclass frontendClazz = env->FindClass("android/media/tv/tuner/Tuner$Frontend");
+ gFields.frontendInitID =
+ env->GetMethodID(frontendClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
+
+ jclass filterClazz = env->FindClass("android/media/tv/tuner/Tuner$Filter");
+ gFields.filterInitID =
+ env->GetMethodID(filterClazz, "<init>", "(Landroid/media/tv/tuner/Tuner;I)V");
}
static void android_media_tv_Tuner_native_setup(JNIEnv *env, jobject thiz) {
@@ -106,9 +256,38 @@
setTuner(env,thiz, tuner);
}
+static jobject android_media_tv_Tuner_get_frontend_ids(JNIEnv *env, jobject thiz) {
+ sp<JTuner> tuner = getTuner(env, thiz);
+ return tuner->getFrontendIds();
+}
+
+static jobject android_media_tv_Tuner_open_frontend_by_id(JNIEnv *env, jobject thiz, jint id) {
+ sp<JTuner> tuner = getTuner(env, thiz);
+ return tuner->openFrontendById(id);
+}
+
+static jobject android_media_tv_Tuner_open_filter(
+ JNIEnv *env, jobject thiz, jint type, jint subType, jint bufferSize) {
+ sp<JTuner> tuner = getTuner(env, thiz);
+ DemuxFilterType filterType {
+ .mainType = static_cast<DemuxFilterMainType>(type),
+ };
+
+ // TODO: other sub types
+ filterType.subType.tsFilterType(static_cast<DemuxTsFilterType>(subType));
+
+ return tuner->openFilter(filterType, bufferSize);
+}
+
static const JNINativeMethod gMethods[] = {
{ "nativeInit", "()V", (void *)android_media_tv_Tuner_native_init },
{ "nativeSetup", "()V", (void *)android_media_tv_Tuner_native_setup },
+ { "nativeGetFrontendIds", "()Ljava/util/List;",
+ (void *)android_media_tv_Tuner_get_frontend_ids },
+ { "nativeOpenFrontendById", "(I)Landroid/media/tv/tuner/Tuner$Frontend;",
+ (void *)android_media_tv_Tuner_open_frontend_by_id },
+ { "nativeOpenFilter", "(III)Landroid/media/tv/tuner/Tuner$Filter;",
+ (void *)android_media_tv_Tuner_open_filter },
};
static int register_android_media_tv_Tuner(JNIEnv *env) {
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index e7d5924..7a889c3 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -18,24 +18,65 @@
#define _ANDROID_MEDIA_TV_TUNER_H_
#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <unordered_map>
#include <utils/RefBase.h>
#include "jni.h"
+using ::android::hardware::Return;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using ::android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using ::android::hardware::tv::tuner::V1_0::FrontendEventType;
+using ::android::hardware::tv::tuner::V1_0::FrontendId;
+using ::android::hardware::tv::tuner::V1_0::FrontendScanMessage;
+using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
+using ::android::hardware::tv::tuner::V1_0::IDemux;
+using ::android::hardware::tv::tuner::V1_0::IFilter;
+using ::android::hardware::tv::tuner::V1_0::IFilterCallback;
+using ::android::hardware::tv::tuner::V1_0::IFrontend;
+using ::android::hardware::tv::tuner::V1_0::IFrontendCallback;
using ::android::hardware::tv::tuner::V1_0::ITuner;
namespace android {
+struct FilterCallback : public IFilterCallback {
+ virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent);
+ virtual Return<void> onFilterStatus(const DemuxFilterStatus status);
+};
+
+struct FrontendCallback : public IFrontendCallback {
+ FrontendCallback(jweak tunerObj, FrontendId id);
+
+ virtual Return<void> onEvent(FrontendEventType frontendEventType);
+ virtual Return<void> onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage);
+ virtual Return<void> onScanMessage(
+ FrontendScanMessageType type, const FrontendScanMessage& message);
+
+ jweak mObject;
+ FrontendId mId;
+};
+
struct JTuner : public RefBase {
JTuner(JNIEnv *env, jobject thiz);
sp<ITuner> getTunerService();
+ jobject getFrontendIds();
+ jobject openFrontendById(int id);
+ jobject openFilter(DemuxFilterType type, int bufferSize);
protected:
+ bool openDemux();
virtual ~JTuner();
private:
jclass mClass;
jweak mObject;
static sp<ITuner> mTuner;
+ hidl_vec<FrontendId> mFeIds;
+ sp<IFrontend> mFe;
+ sp<IDemux> mDemux;
+ int mDemuxId;
+ std::unordered_map<int, sp<IFilter>> mFilters;
};
} // namespace android
diff --git a/media/lib/signer/Android.bp b/media/lib/signer/Android.bp
index 6b03e4d..3b25787 100644
--- a/media/lib/signer/Android.bp
+++ b/media/lib/signer/Android.bp
@@ -17,7 +17,5 @@
java_sdk_library {
name: "com.android.mediadrm.signer",
srcs: ["java/**/*.java"],
- api_srcs: [":framework-all-sources"],
- libs: ["framework-all"],
api_packages: ["com.android.mediadrm.signer"],
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java
index 74bf1a2..de353bf 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaInserterTest.java
@@ -42,6 +42,7 @@
public class MediaInserterTest extends InstrumentationTestCase {
+ private static final String TEST_FEATURE_ID = "testFeature";
private MediaInserter mMediaInserter;
private static final int TEST_BUFFER_SIZE = 10;
private @Mock IContentProvider mMockProvider;
@@ -86,7 +87,8 @@
MockitoAnnotations.initMocks(this);
final ContentProviderClient client = new ContentProviderClient(
- getInstrumentation().getContext().getContentResolver(), mMockProvider, true);
+ getInstrumentation().getContext().createFeatureContext(TEST_FEATURE_ID)
+ .getContentResolver(), mMockProvider, true);
mMediaInserter = new MediaInserter(client, TEST_BUFFER_SIZE);
mPackageName = getInstrumentation().getContext().getPackageName();
mFilesCounter = 0;
@@ -142,31 +144,36 @@
fillBuffer(sVideoUri, TEST_BUFFER_SIZE - 2);
fillBuffer(sImagesUri, TEST_BUFFER_SIZE - 1);
- verify(mMockProvider, never()).bulkInsert(eq(mPackageName), any(), any());
+ verify(mMockProvider, never()).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ any());
}
@SmallTest
public void testInsertContentsEqualToBufferSize() throws Exception {
- when(mMockProvider.bulkInsert(eq(mPackageName), any(), any())).thenReturn(1);
+ when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ any())).thenReturn(1);
fillBuffer(sFilesUri, TEST_BUFFER_SIZE);
fillBuffer(sAudioUri, TEST_BUFFER_SIZE);
fillBuffer(sVideoUri, TEST_BUFFER_SIZE);
fillBuffer(sImagesUri, TEST_BUFFER_SIZE);
- verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), any(), any());
+ verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ any());
}
@SmallTest
public void testInsertContentsMoreThanBufferSize() throws Exception {
- when(mMockProvider.bulkInsert(eq(mPackageName), any(), any())).thenReturn(1);
+ when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ any())).thenReturn(1);
fillBuffer(sFilesUri, TEST_BUFFER_SIZE + 1);
fillBuffer(sAudioUri, TEST_BUFFER_SIZE + 2);
fillBuffer(sVideoUri, TEST_BUFFER_SIZE + 3);
fillBuffer(sImagesUri, TEST_BUFFER_SIZE + 4);
- verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), any(), any());
+ verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ any());
}
@SmallTest
@@ -176,7 +183,8 @@
@SmallTest
public void testFlushAllWithSomeContents() throws Exception {
- when(mMockProvider.bulkInsert(eq(mPackageName), any(), any())).thenReturn(1);
+ when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ any())).thenReturn(1);
fillBuffer(sFilesUri, TEST_BUFFER_SIZE - 4);
fillBuffer(sAudioUri, TEST_BUFFER_SIZE - 3);
@@ -184,12 +192,14 @@
fillBuffer(sImagesUri, TEST_BUFFER_SIZE - 1);
mMediaInserter.flushAll();
- verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), any(), any());
+ verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ any());
}
@SmallTest
public void testInsertContentsAfterFlushAll() throws Exception {
- when(mMockProvider.bulkInsert(eq(mPackageName), any(), any())).thenReturn(1);
+ when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ any())).thenReturn(1);
fillBuffer(sFilesUri, TEST_BUFFER_SIZE - 4);
fillBuffer(sAudioUri, TEST_BUFFER_SIZE - 3);
@@ -202,15 +212,20 @@
fillBuffer(sVideoUri, TEST_BUFFER_SIZE + 3);
fillBuffer(sImagesUri, TEST_BUFFER_SIZE + 4);
- verify(mMockProvider, times(8)).bulkInsert(eq(mPackageName), any(), any());
+ verify(mMockProvider, times(8)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), any(),
+ any());
}
@SmallTest
public void testInsertContentsWithDifferentSizePerContentType() throws Exception {
- when(mMockProvider.bulkInsert(eq(mPackageName), eqUri(sFilesUri), any())).thenReturn(1);
- when(mMockProvider.bulkInsert(eq(mPackageName), eqUri(sAudioUri), any())).thenReturn(1);
- when(mMockProvider.bulkInsert(eq(mPackageName), eqUri(sVideoUri), any())).thenReturn(1);
- when(mMockProvider.bulkInsert(eq(mPackageName), eqUri(sImagesUri), any())).thenReturn(1);
+ when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sFilesUri),
+ any())).thenReturn(1);
+ when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sAudioUri),
+ any())).thenReturn(1);
+ when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sVideoUri),
+ any())).thenReturn(1);
+ when(mMockProvider.bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID), eqUri(sImagesUri),
+ any())).thenReturn(1);
for (int i = 0; i < TEST_BUFFER_SIZE; ++i) {
fillBuffer(sFilesUri, 1);
@@ -219,9 +234,13 @@
fillBuffer(sImagesUri, 4);
}
- verify(mMockProvider, times(1)).bulkInsert(eq(mPackageName), eqUri(sFilesUri), any());
- verify(mMockProvider, times(2)).bulkInsert(eq(mPackageName), eqUri(sAudioUri), any());
- verify(mMockProvider, times(3)).bulkInsert(eq(mPackageName), eqUri(sVideoUri), any());
- verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eqUri(sImagesUri), any());
+ verify(mMockProvider, times(1)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID),
+ eqUri(sFilesUri), any());
+ verify(mMockProvider, times(2)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID),
+ eqUri(sAudioUri), any());
+ verify(mMockProvider, times(3)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID),
+ eqUri(sVideoUri), any());
+ verify(mMockProvider, times(4)).bulkInsert(eq(mPackageName), eq(TEST_FEATURE_ID),
+ eqUri(sImagesUri), any());
}
}
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
index ca43d04..acf8998 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouterManagerTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
@@ -272,29 +273,28 @@
@Test
public void testControlVolumeWithRouter() throws Exception {
- MediaRouter2.Callback mockCallback = mock(MediaRouter2.Callback.class);
-
Map<String, MediaRoute2Info> routes = waitAndGetRoutes(CONTROL_CATEGORIES_ALL);
- mRouter2.registerCallback(mExecutor, mockCallback);
MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
int originalVolume = volRoute.getVolume();
int deltaVolume = (originalVolume == volRoute.getVolumeMax() ? -1 : 1);
- int targetVolume = originalVolume + deltaVolume;
- mRouter2.requestSetVolume(volRoute, targetVolume);
- verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
- .onRouteChanged(argThat(route ->
- route.getId().equals(volRoute.getId())
- && route.getVolume() == targetVolume));
+ CountDownLatch latch1 = new CountDownLatch(1);
+ MediaRouter2.Callback callback1 =
+ createVolumeChangeCallback(ROUTE_ID_VARIABLE_VOLUME,
+ originalVolume + deltaVolume, latch1);
+ mRouter2.registerCallback(mExecutor, callback1);
+ mRouter2.requestUpdateVolume(volRoute, deltaVolume);
+ assertTrue(latch1.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ mRouter2.unregisterCallback(callback1);
- mRouter2.requestUpdateVolume(volRoute, -deltaVolume);
- verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
- .onRouteChanged(argThat(route ->
- route.getId().equals(volRoute.getId())
- && route.getVolume() == originalVolume));
-
- mRouter2.unregisterCallback(mockCallback);
+ CountDownLatch latch2 = new CountDownLatch(1);
+ MediaRouter2.Callback callback2 =
+ createVolumeChangeCallback(ROUTE_ID_VARIABLE_VOLUME, originalVolume, latch2);
+ mRouter2.registerCallback(mExecutor, callback2);
+ mRouter2.requestSetVolume(volRoute, originalVolume);
+ assertTrue(latch1.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ mRouter2.unregisterCallback(callback1);
}
@Test
@@ -312,13 +312,13 @@
int targetVolume = originalVolume + deltaVolume;
mManager.requestSetVolume(volRoute, targetVolume);
- verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
+ verify(managerCallback, timeout(TIMEOUT_MS).atLeastOnce())
.onRouteChanged(argThat(route ->
route.getId().equals(volRoute.getId())
&& route.getVolume() == targetVolume));
mManager.requestUpdateVolume(volRoute, -deltaVolume);
- verify(mockCallback, timeout(TIMEOUT_MS).atLeastOnce())
+ verify(managerCallback, timeout(TIMEOUT_MS).atLeastOnce())
.onRouteChanged(argThat(route ->
route.getId().equals(volRoute.getId())
&& route.getVolume() == originalVolume));
@@ -347,14 +347,14 @@
CountDownLatch latch = new CountDownLatch(1);
MediaRouter2.Callback callback = new MediaRouter2.Callback() {
@Override
- public void onRoutesChanged(List<MediaRoute2Info> routes) {
- if (routes.size() > 0) latch.countDown();
+ public void onRoutesAdded(List<MediaRoute2Info> added) {
+ if (added.size() > 0) latch.countDown();
}
};
mRouter2.setControlCategories(controlCategories);
mRouter2.registerCallback(mExecutor, callback);
try {
- latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
return createRouteMap(mRouter2.getRoutes());
} finally {
mRouter2.unregisterCallback(callback);
@@ -370,14 +370,18 @@
MediaRouter2Manager.Callback managerCallback = new MediaRouter2Manager.Callback() {
@Override
public void onRoutesChanged(List<MediaRoute2Info> routes) {
- if (routes.size() > 0) latch.countDown();
+ if (routes.size() > 0) {
+ latch.countDown();
+ }
}
};
mManager.registerCallback(mExecutor, managerCallback);
mRouter2.setControlCategories(controlCategories);
mRouter2.registerCallback(mExecutor, routerCallback);
try {
- latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ assertTrue(latch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ //TODO: currently this returns empty list occasionally.
+ //Maybe due to control category is not set yet
return createRouteMap(mManager.getAvailableRoutes(mPackageName));
} finally {
mRouter2.unregisterCallback(routerCallback);
@@ -385,6 +389,20 @@
}
}
+ MediaRouter2.Callback createVolumeChangeCallback(String routeId,
+ int targetVolume, CountDownLatch latch) {
+ MediaRouter2.Callback callback = new MediaRouter2.Callback() {
+ @Override
+ public void onRoutesChanged(List<MediaRoute2Info> changed) {
+ MediaRoute2Info volRoute = createRouteMap(changed).get(routeId);
+ if (volRoute != null && volRoute.getVolume() == targetVolume) {
+ latch.countDown();
+ }
+ }
+ };
+ return callback;
+ }
+
// Helper for getting routes easily
static Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) {
Map<String, MediaRoute2Info> routeMap = new HashMap<>();
diff --git a/mime/java-res/android.mime.types b/mime/java-res/android.mime.types
index 7a5299f..ce022a8 100644
--- a/mime/java-res/android.mime.types
+++ b/mime/java-res/android.mime.types
@@ -48,6 +48,9 @@
?application/epub+zip epub
?application/pkix-cert cer
?application/rss+xml rss
+?application/sdp sdp
+?application/smil+xml smil
+?application/ttml+xml ttml dfxp
?application/vnd.android.ota ota
?application/vnd.apple.mpegurl m3u8
?application/vnd.ms-pki.stl stl
@@ -67,12 +70,13 @@
?application/x-x509-server-cert crt
?application/x-x509-user-cert crt
-?audio/3gpp 3gpp
+?audio/3gpp 3gpp 3ga
?audio/aac-adts aac
+?audio/ac3 ac3 a52
?audio/imelody imy
?audio/midi rtttl xmf
?audio/mobile-xmf mxmf
-?audio/mp4 m4a
+?audio/mp4 m4a m4b m4p f4a f4b f4p
?audio/mpegurl m3u
?audio/sp-midi smf
?audio/x-matroska mka
@@ -101,10 +105,11 @@
?text/xml xml
?text/x-vcard vcf
-?video/3gpp2 3gpp2 3g2
+?video/3gpp2 3gpp2 3gp2 3g2
?video/3gpp 3gpp
?video/avi avi
?video/m4v m4v
+?video/mp4 m4v f4v mp4v mpeg4
?video/mp2p mpeg
?video/mp2t m2ts mts
?video/mp2ts ts
@@ -129,11 +134,11 @@
application/pgp-signature pgp
application/x-x509-ca-cert crt
-audio/aac aac
+audio/aac aac adts adt
audio/basic snd
audio/flac flac
audio/midi rtx
-audio/mpeg mp3 m4a m4r
+audio/mpeg mp3 mp2 mp1 mpa m4a m4r
audio/x-mpegurl m3u m3u8
image/jpeg jpg
image/x-ms-bmp bmp
@@ -141,6 +146,6 @@
text/x-c++hdr hpp
text/x-c++src cpp
video/3gpp 3gpp
-video/mpeg mpeg
+video/mpeg mpeg mpeg2 mpv2 mp2v m2v m2t mpeg1 mpv1 mp1v m1v
video/quicktime mov
video/x-matroska mkv
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml
index 329225c..981c129 100644
--- a/packages/CarSystemUI/res/values/config.xml
+++ b/packages/CarSystemUI/res/values/config.xml
@@ -58,7 +58,6 @@
<!-- SystemUI Services: The classes of the stuff to start. -->
<string-array name="config_systemUIServiceComponents" translatable="false">
<item>com.android.systemui.util.NotificationChannels</item>
- <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
<item>com.android.systemui.keyguard.KeyguardViewMediator</item>
<item>com.android.systemui.recents.Recents</item>
<item>com.android.systemui.volume.VolumeUI</item>
diff --git a/packages/CarSystemUI/res/values/integers_car.xml b/packages/CarSystemUI/res/values/integers_car.xml
index fb67b30..d6c16cb 100644
--- a/packages/CarSystemUI/res/values/integers_car.xml
+++ b/packages/CarSystemUI/res/values/integers_car.xml
@@ -34,4 +34,7 @@
<!-- The delay before the unlock dialog pops up -->
<integer name="unlock_dialog_delay_ms">0</integer>
+ <!-- Timeout values in milliseconds for displaying volume dialog-->
+ <integer name="car_volume_dialog_display_normal_timeout">3000</integer>
+ <integer name="car_volume_dialog_display_hovering_timeout">16000</integer>
</resources>
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarComponentBinder.java b/packages/CarSystemUI/src/com/android/systemui/CarComponentBinder.java
new file mode 100644
index 0000000..f11eff8
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/CarComponentBinder.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import com.android.systemui.dagger.DefaultActivityBinder;
+import com.android.systemui.dagger.DefaultBroadcastReceiverBinder;
+import com.android.systemui.dagger.DefaultServiceBinder;
+
+import dagger.Module;
+
+/**
+ * Supply Activities, Services, and SystemUI Objects for CarSystemUI.
+ */
+@Module(includes = {
+ DefaultActivityBinder.class,
+ DefaultBroadcastReceiverBinder.class,
+ DefaultServiceBinder.class,
+ CarSystemUIBinder.class})
+public class CarComponentBinder {
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
index 8e0a3eb..d3d9b28 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
@@ -16,7 +16,22 @@
package com.android.systemui;
+import com.android.systemui.biometrics.AuthController;
+import com.android.systemui.globalactions.GlobalActionsComponent;
+import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.navigationbar.car.CarNavigationBar;
+import com.android.systemui.pip.PipUI;
+import com.android.systemui.power.PowerUI;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsModule;
+import com.android.systemui.statusbar.car.CarStatusBar;
+import com.android.systemui.statusbar.car.CarStatusBarModule;
+import com.android.systemui.statusbar.notification.InstantAppNotifier;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.tv.TvStatusBar;
+import com.android.systemui.theme.ThemeOverlayController;
+import com.android.systemui.util.leak.GarbageMonitor;
+import com.android.systemui.volume.VolumeUI;
import dagger.Binds;
import dagger.Module;
@@ -24,11 +39,114 @@
import dagger.multibindings.IntoMap;
/** Binder for car specific {@link SystemUI} modules. */
-@Module
+@Module(includes = {RecentsModule.class, CarStatusBarModule.class})
public abstract class CarSystemUIBinder {
+ /** Inject into AuthController. */
+ @Binds
+ @IntoMap
+ @ClassKey(AuthController.class)
+ public abstract SystemUI bindAuthController(AuthController service);
+
/** */
@Binds
@IntoMap
@ClassKey(CarNavigationBar.class)
public abstract SystemUI bindCarNavigationBar(CarNavigationBar sysui);
+
+ /** Inject into GarbageMonitor.Service. */
+ @Binds
+ @IntoMap
+ @ClassKey(GarbageMonitor.Service.class)
+ public abstract SystemUI bindGarbageMonitorService(GarbageMonitor.Service service);
+
+ /** Inject into GlobalActionsComponent. */
+ @Binds
+ @IntoMap
+ @ClassKey(GlobalActionsComponent.class)
+ public abstract SystemUI bindGlobalActionsComponent(GlobalActionsComponent sysui);
+
+ /** Inject into InstantAppNotifier. */
+ @Binds
+ @IntoMap
+ @ClassKey(InstantAppNotifier.class)
+ public abstract SystemUI bindInstantAppNotifier(InstantAppNotifier sysui);
+
+ /** Inject into KeyguardViewMediator. */
+ @Binds
+ @IntoMap
+ @ClassKey(KeyguardViewMediator.class)
+ public abstract SystemUI bindKeyguardViewMediator(KeyguardViewMediator sysui);
+
+ /** Inject into LatencyTests. */
+ @Binds
+ @IntoMap
+ @ClassKey(LatencyTester.class)
+ public abstract SystemUI bindLatencyTester(LatencyTester sysui);
+
+ /** Inject into PipUI. */
+ @Binds
+ @IntoMap
+ @ClassKey(PipUI.class)
+ public abstract SystemUI bindPipUI(PipUI sysui);
+
+ /** Inject into PowerUI. */
+ @Binds
+ @IntoMap
+ @ClassKey(PowerUI.class)
+ public abstract SystemUI bindPowerUI(PowerUI sysui);
+
+ /** Inject into Recents. */
+ @Binds
+ @IntoMap
+ @ClassKey(Recents.class)
+ public abstract SystemUI bindRecents(Recents sysui);
+
+ /** Inject into ScreenDecorations. */
+ @Binds
+ @IntoMap
+ @ClassKey(ScreenDecorations.class)
+ public abstract SystemUI bindScreenDecorations(ScreenDecorations sysui);
+
+ /** Inject into SizeCompatModeActivityController. */
+ @Binds
+ @IntoMap
+ @ClassKey(SizeCompatModeActivityController.class)
+ public abstract SystemUI bindsSizeCompatModeActivityController(
+ SizeCompatModeActivityController sysui);
+
+ /** Inject into SliceBroadcastRelayHandler. */
+ @Binds
+ @IntoMap
+ @ClassKey(SliceBroadcastRelayHandler.class)
+ public abstract SystemUI bindSliceBroadcastRelayHandler(SliceBroadcastRelayHandler sysui);
+
+ /** Inject into ThemeOverlayController. */
+ @Binds
+ @IntoMap
+ @ClassKey(ThemeOverlayController.class)
+ public abstract SystemUI bindThemeOverlayController(ThemeOverlayController sysui);
+
+ /** Inject into StatusBar. */
+ @Binds
+ @IntoMap
+ @ClassKey(StatusBar.class)
+ public abstract SystemUI bindsStatusBar(CarStatusBar sysui);
+
+ /** Inject into TvStatusBar. */
+ @Binds
+ @IntoMap
+ @ClassKey(TvStatusBar.class)
+ public abstract SystemUI bindsTvStatusBar(TvStatusBar sysui);
+
+ /** Inject into StatusBarGoogle. */
+ @Binds
+ @IntoMap
+ @ClassKey(CarStatusBar.class)
+ public abstract SystemUI bindsCarStatusBar(CarStatusBar sysui);
+
+ /** Inject into VolumeUI. */
+ @Binds
+ @IntoMap
+ @ClassKey(VolumeUI.class)
+ public abstract SystemUI bindVolumeUI(VolumeUI sysui);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index 93e553f..a65cf2e 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -28,6 +28,7 @@
import com.android.systemui.dock.DockManagerImpl;
import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.EnhancedEstimatesImpl;
+import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.car.CarStatusBar;
@@ -46,8 +47,6 @@
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
-import dagger.multibindings.ClassKey;
-import dagger.multibindings.IntoMap;
@Module
abstract class CarSystemUIModule {
@@ -72,6 +71,12 @@
@Singleton
@Provides
+ static Divider provideDivider(Context context) {
+ return new Divider(context);
+ }
+
+ @Singleton
+ @Provides
@Named(LEAK_REPORT_EMAIL_NAME)
static String provideLeakReportEmail() {
return "buganizer-system+181579@google.com";
@@ -105,11 +110,6 @@
public abstract StatusBar bindStatusBar(CarStatusBar statusBar);
@Binds
- @IntoMap
- @ClassKey(StatusBar.class)
- public abstract SystemUI providesStatusBar(CarStatusBar statusBar);
-
- @Binds
abstract VolumeDialogComponent bindVolumeDialogComponent(
CarVolumeDialogComponent carVolumeDialogComponent);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java
index c2847c8..51b263e 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIRootComponent.java
@@ -29,6 +29,7 @@
@Singleton
@Component(
modules = {
+ CarComponentBinder.class,
DependencyProvider.class,
DependencyBinder.class,
SystemUIFactory.ContextHolder.class,
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
index 98b91ebd..af92767 100644
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
@@ -53,13 +53,13 @@
private final CarNavigationBarController mCarNavigationBarController;
private final WindowManager mWindowManager;
private final DeviceProvisionedController mDeviceProvisionedController;
+ private final CommandQueue mCommandQueue;
private final Lazy<FacetButtonTaskStackListener> mFacetButtonTaskStackListener;
private final Handler mMainHandler;
private final Lazy<KeyguardStateController> mKeyguardStateController;
private final Lazy<NavigationBarController> mNavigationBarController;
private IStatusBarService mBarService;
- private CommandQueue mCommandQueue;
private ActivityManagerWrapper mActivityManagerWrapper;
// If the nav bar should be hidden when the soft keyboard is visible.
@@ -83,6 +83,7 @@
CarNavigationBarController carNavigationBarController,
WindowManager windowManager,
DeviceProvisionedController deviceProvisionedController,
+ CommandQueue commandQueue,
Lazy<FacetButtonTaskStackListener> facetButtonTaskStackListener,
@MainHandler Handler mainHandler,
Lazy<KeyguardStateController> keyguardStateController,
@@ -91,6 +92,7 @@
mCarNavigationBarController = carNavigationBarController;
mWindowManager = windowManager;
mDeviceProvisionedController = deviceProvisionedController;
+ mCommandQueue = commandQueue;
mFacetButtonTaskStackListener = facetButtonTaskStackListener;
mMainHandler = mainHandler;
mKeyguardStateController = keyguardStateController;
@@ -109,7 +111,6 @@
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
// Connect into the status bar manager service
- mCommandQueue = getComponent(CommandQueue.class);
mCommandQueue.addCallback(this);
RegisterStatusBarResult result = null;
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarView.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarView.java
index c245508..28da169 100644
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBarView.java
@@ -25,6 +25,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.navigationbar.car.CarNavigationBarController.NotificationsShadeController;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBarIconController;
/**
@@ -63,7 +64,8 @@
// container is in the view.
StatusBarIconController.DarkIconManager mDarkIconManager =
new StatusBarIconController.DarkIconManager(
- mStatusIcons.findViewById(R.id.statusIcons));
+ mStatusIcons.findViewById(R.id.statusIcons),
+ Dependency.get(CommandQueue.class));
mDarkIconManager.setShouldLog(true);
Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index ce763b9..ab63b06 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -27,7 +27,6 @@
import android.car.drivingstate.CarDrivingStateEvent;
import android.car.drivingstate.CarUxRestrictionsManager;
import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
-import android.car.trust.CarTrustAgentEnrollmentManager;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -81,6 +80,9 @@
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.car.CarQSFragment;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.NavigationBarController;
@@ -91,6 +93,7 @@
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
@@ -127,24 +130,22 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.util.InjectionInflationController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Map;
+import java.util.Optional;
-import javax.inject.Inject;
import javax.inject.Named;
-import javax.inject.Singleton;
import dagger.Lazy;
/**
* A status bar tailored for the automotive use case.
*/
-@Singleton
public class CarStatusBar extends StatusBar implements CarBatteryController.BatteryViewHandler {
private static final String TAG = "CarStatusBar";
// used to calculate how fast to open or close the window
@@ -221,6 +222,8 @@
// Whether heads-up notifications should be shown when shade is open.
private boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen;
+ private CarUxRestrictionManagerWrapper mCarUxRestrictionManagerWrapper;
+
private final CarPowerStateListener mCarPowerStateListener =
(int state) -> {
// When the car powers on, clear all notifications and mute/unread states.
@@ -235,7 +238,6 @@
}
};
- @Inject
public CarStatusBar(
Context context,
FeatureFlags featureFlags,
@@ -244,7 +246,6 @@
KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarIconController statusBarIconController,
DozeLog dozeLog,
- InjectionInflationController injectionInflationController,
PulseExpansionHandler pulseExpansionHandler,
NotificationWakeUpCoordinator notificationWakeUpCoordinator,
KeyguardBypassController keyguardBypassController,
@@ -300,7 +301,11 @@
DozeServiceHost dozeServiceHost,
PowerManager powerManager,
DozeScrimController dozeScrimController,
-
+ CommandQueue commandQueue,
+ PluginManager pluginManager,
+ RemoteInputUriController remoteInputUriController,
+ Optional<Divider> dividerOptional,
+ SuperStatusBarViewFactory superStatusBarViewFactory,
/* Car Settings injected components. */
CarNavigationBarController carNavigationBarController) {
super(
@@ -311,7 +316,6 @@
keyguardUpdateMonitor,
statusBarIconController,
dozeLog,
- injectionInflationController,
pulseExpansionHandler,
notificationWakeUpCoordinator,
keyguardBypassController,
@@ -362,11 +366,17 @@
notifLog,
dozeParameters,
scrimController,
+ null /* keyguardLiftController */,
lockscreenWallpaperLazy,
biometricUnlockControllerLazy,
dozeServiceHost,
powerManager,
- dozeScrimController);
+ dozeScrimController,
+ commandQueue,
+ pluginManager,
+ remoteInputUriController,
+ dividerOptional,
+ superStatusBarViewFactory);
mScrimController = scrimController;
mCarNavigationBarController = carNavigationBarController;
}
@@ -428,14 +438,16 @@
}
});
+ // Used by onDrivingStateChanged and it can be called inside
+ // DrivingStateHelper.connectToCarService()
+ mSwitchToGuestTimer = new SwitchToGuestTimer(mContext);
+
// Register a listener for driving state changes.
mDrivingStateHelper = new DrivingStateHelper(mContext, this::onDrivingStateChanged);
mDrivingStateHelper.connectToCarService();
mPowerManagerHelper = new PowerManagerHelper(mContext, mCarPowerStateListener);
mPowerManagerHelper.connectToCarService();
-
- mSwitchToGuestTimer = new SwitchToGuestTimer(mContext);
}
private void resetSystemBarsIfNecessary() {
@@ -572,13 +584,22 @@
animateCollapsePanels();
}
});
- Car car = Car.createCar(mContext);
- CarUxRestrictionsManager carUxRestrictionsManager = (CarUxRestrictionsManager)
- car.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);
CarNotificationListener carNotificationListener = new CarNotificationListener();
- CarUxRestrictionManagerWrapper carUxRestrictionManagerWrapper =
- new CarUxRestrictionManagerWrapper();
- carUxRestrictionManagerWrapper.setCarUxRestrictionsManager(carUxRestrictionsManager);
+ mCarUxRestrictionManagerWrapper = new CarUxRestrictionManagerWrapper();
+ // This can take time if car service is not ready up to this time.
+ // TODO(b/142808072) Refactor CarUxRestrictionManagerWrapper to allow setting
+ // CarUxRestrictionsManager later and switch to Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT.
+ Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_WAIT_FOREVER,
+ (car, ready) -> {
+ if (!ready) {
+ return;
+ }
+ CarUxRestrictionsManager carUxRestrictionsManager =
+ (CarUxRestrictionsManager)
+ car.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE);
+ mCarUxRestrictionManagerWrapper.setCarUxRestrictionsManager(
+ carUxRestrictionsManager);
+ });
mNotificationDataManager = new NotificationDataManager();
mNotificationDataManager.setOnUnseenCountUpdateListener(
@@ -598,7 +619,7 @@
mNotificationClickHandlerFactory, mNotificationDataManager);
mNotificationClickHandlerFactory.setNotificationDataManager(mNotificationDataManager);
- carNotificationListener.registerAsSystemService(mContext, carUxRestrictionManagerWrapper,
+ carNotificationListener.registerAsSystemService(mContext, mCarUxRestrictionManagerWrapper,
carHeadsUpNotificationManager, mNotificationDataManager);
mNotificationView = mStatusBarWindow.findViewById(R.id.notification_view);
@@ -698,7 +719,7 @@
mNotificationView,
PreprocessingManager.getInstance(mContext),
carNotificationListener,
- carUxRestrictionManagerWrapper,
+ mCarUxRestrictionManagerWrapper,
mNotificationDataManager);
mNotificationViewController.enable();
}
@@ -947,12 +968,8 @@
UserSwitcherController userSwitcherController =
Dependency.get(UserSwitcherController.class);
if (userSwitcherController.useFullscreenUserSwitcher()) {
- Car car = Car.createCar(mContext);
- CarTrustAgentEnrollmentManager enrollmentManager = (CarTrustAgentEnrollmentManager) car
- .getCarManager(Car.CAR_TRUST_AGENT_ENROLLMENT_SERVICE);
mFullscreenUserSwitcher = new FullscreenUserSwitcher(this,
- mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub),
- enrollmentManager, mContext);
+ mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub), mContext);
} else {
super.createUserSwitcher();
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
new file mode 100644
index 0000000..7de2212
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.car;
+
+import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.util.DisplayMetrics;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.UiOffloadThread;
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.navigationbar.car.CarNavigationBarController;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationViewHierarchyManager;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.StatusBarDependenciesModule;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.phone.AutoHideController;
+import com.android.systemui.statusbar.phone.BiometricUnlockController;
+import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.DozeScrimController;
+import com.android.systemui.statusbar.phone.DozeServiceHost;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.LockscreenWallpaper;
+import com.android.systemui.statusbar.phone.NotificationGroupAlertTransferHelper;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
+import com.android.systemui.statusbar.phone.StatusBarWindowViewController;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.ZenModeController;
+
+import java.util.Optional;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger Module providing {@link CarStatusBar}.
+ */
+@Module(includes = {StatusBarDependenciesModule.class})
+public class CarStatusBarModule {
+ /**
+ * Provides our instance of StatusBar which is considered optional.
+ */
+ @Provides
+ @Singleton
+ static CarStatusBar provideStatusBar(
+ Context context,
+ FeatureFlags featureFlags,
+ LightBarController lightBarController,
+ AutoHideController autoHideController,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ StatusBarIconController statusBarIconController,
+ DozeLog dozeLog,
+ PulseExpansionHandler pulseExpansionHandler,
+ NotificationWakeUpCoordinator notificationWakeUpCoordinator,
+ KeyguardBypassController keyguardBypassController,
+ KeyguardStateController keyguardStateController,
+ HeadsUpManagerPhone headsUpManagerPhone,
+ DynamicPrivacyController dynamicPrivacyController,
+ BypassHeadsUpNotifier bypassHeadsUpNotifier,
+ @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
+ Lazy<NewNotifPipeline> newNotifPipeline,
+ FalsingManager falsingManager,
+ BroadcastDispatcher broadcastDispatcher,
+ RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
+ NotificationGutsManager notificationGutsManager,
+ NotificationLogger notificationLogger,
+ NotificationEntryManager notificationEntryManager,
+ NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationViewHierarchyManager notificationViewHierarchyManager,
+ ForegroundServiceController foregroundServiceController,
+ AppOpsController appOpsController,
+ KeyguardViewMediator keyguardViewMediator,
+ ZenModeController zenModeController,
+ NotificationAlertingManager notificationAlertingManager,
+ DisplayMetrics displayMetrics,
+ MetricsLogger metricsLogger,
+ UiOffloadThread uiOffloadThread,
+ NotificationMediaManager notificationMediaManager,
+ NotificationLockscreenUserManager lockScreenUserManager,
+ NotificationRemoteInputManager remoteInputManager,
+ UserSwitcherController userSwitcherController,
+ NetworkController networkController,
+ BatteryController batteryController,
+ SysuiColorExtractor colorExtractor,
+ ScreenLifecycle screenLifecycle,
+ WakefulnessLifecycle wakefulnessLifecycle,
+ SysuiStatusBarStateController statusBarStateController,
+ VibratorHelper vibratorHelper,
+ BubbleController bubbleController,
+ NotificationGroupManager groupManager,
+ NotificationGroupAlertTransferHelper groupAlertTransferHelper,
+ VisualStabilityManager visualStabilityManager,
+ DeviceProvisionedController deviceProvisionedController,
+ NavigationBarController navigationBarController,
+ AssistManager assistManager,
+ NotificationListener notificationListener,
+ ConfigurationController configurationController,
+ StatusBarWindowController statusBarWindowController,
+ StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder,
+ NotifLog notifLog,
+ DozeParameters dozeParameters,
+ ScrimController scrimController,
+ Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
+ Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+ DozeServiceHost dozeServiceHost,
+ PowerManager powerManager,
+ DozeScrimController dozeScrimController,
+ CommandQueue commandQueue,
+ PluginManager pluginManager,
+ RemoteInputUriController remoteInputUriController,
+ Optional<Divider> dividerOptional,
+ SuperStatusBarViewFactory superStatusBarViewFactory,
+ CarNavigationBarController carNavigationBarController) {
+ return new CarStatusBar(
+ context,
+ featureFlags,
+ lightBarController,
+ autoHideController,
+ keyguardUpdateMonitor,
+ statusBarIconController,
+ dozeLog,
+ pulseExpansionHandler,
+ notificationWakeUpCoordinator,
+ keyguardBypassController,
+ keyguardStateController,
+ headsUpManagerPhone,
+ dynamicPrivacyController,
+ bypassHeadsUpNotifier,
+ allowNotificationLongPress,
+ newNotifPipeline,
+ falsingManager,
+ broadcastDispatcher,
+ remoteInputQuickSettingsDisabler,
+ notificationGutsManager,
+ notificationLogger,
+ notificationEntryManager,
+ notificationInterruptionStateProvider,
+ notificationViewHierarchyManager,
+ foregroundServiceController,
+ appOpsController,
+ keyguardViewMediator,
+ zenModeController,
+ notificationAlertingManager,
+ displayMetrics,
+ metricsLogger,
+ uiOffloadThread,
+ notificationMediaManager,
+ lockScreenUserManager,
+ remoteInputManager,
+ userSwitcherController,
+ networkController,
+ batteryController,
+ colorExtractor,
+ screenLifecycle,
+ wakefulnessLifecycle,
+ statusBarStateController,
+ vibratorHelper,
+ bubbleController,
+ groupManager,
+ groupAlertTransferHelper,
+ visualStabilityManager,
+ deviceProvisionedController,
+ navigationBarController,
+ assistManager,
+ notificationListener,
+ configurationController,
+ statusBarWindowController,
+ statusBarWindowViewControllerBuilder,
+ notifLog,
+ dozeParameters,
+ scrimController,
+ lockscreenWallpaperLazy,
+ biometricUnlockControllerLazy,
+ dozeServiceHost,
+ powerManager,
+ dozeScrimController,
+ commandQueue,
+ pluginManager,
+ remoteInputUriController,
+ dividerOptional,
+ superStatusBarViewFactory,
+ carNavigationBarController);
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java
index a442426..cd87e78 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/DrivingStateHelper.java
@@ -17,14 +17,11 @@
package com.android.systemui.statusbar.car;
import android.car.Car;
-import android.car.CarNotConnectedException;
+import android.car.Car.CarServiceLifecycleListener;
import android.car.drivingstate.CarDrivingStateEvent;
import android.car.drivingstate.CarDrivingStateManager;
import android.car.drivingstate.CarDrivingStateManager.CarDrivingStateEventListener;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.ServiceConnection;
-import android.os.IBinder;
import android.util.Log;
import androidx.annotation.NonNull;
@@ -55,16 +52,11 @@
if (mDrivingStateManager == null) {
return false;
}
- try {
- CarDrivingStateEvent currentState = mDrivingStateManager.getCurrentCarDrivingState();
- if (currentState != null) {
- return currentState.eventValue == CarDrivingStateEvent.DRIVING_STATE_IDLING
- || currentState.eventValue == CarDrivingStateEvent.DRIVING_STATE_MOVING;
- }
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Cannot determine current driving state. Car not connected", e);
+ CarDrivingStateEvent currentState = mDrivingStateManager.getCurrentCarDrivingState();
+ if (currentState != null) {
+ return currentState.eventValue == CarDrivingStateEvent.DRIVING_STATE_IDLING
+ || currentState.eventValue == CarDrivingStateEvent.DRIVING_STATE_MOVING;
}
-
return false; // Default to false.
}
@@ -72,55 +64,25 @@
* Establishes connection with the Car service.
*/
public void connectToCarService() {
- mCar = Car.createCar(mContext, mCarConnectionListener);
- if (mCar != null) {
- mCar.connect();
- }
+ mCar = Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
+ mCarServiceLifecycleListener);
}
- /**
- * Disconnects from Car service and cleans up listeners.
- */
- public void disconnectFromCarService() {
- if (mCar != null) {
- mCar.disconnect();
+ private final CarServiceLifecycleListener mCarServiceLifecycleListener = (car, ready) -> {
+ if (!ready) {
+ return;
}
- }
-
- private final ServiceConnection mCarConnectionListener =
- new ServiceConnection() {
- public void onServiceConnected(ComponentName name, IBinder service) {
- logD("Car Service connected");
- try {
- mDrivingStateManager = (CarDrivingStateManager) mCar.getCarManager(
- Car.CAR_DRIVING_STATE_SERVICE);
- if (mDrivingStateManager != null) {
- mDrivingStateManager.registerListener(mDrivingStateHandler);
- mDrivingStateHandler.onDrivingStateChanged(
- mDrivingStateManager.getCurrentCarDrivingState());
- } else {
- Log.e(TAG, "CarDrivingStateService service not available");
- }
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Car not connected", e);
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- destroyDrivingStateManager();
- }
- };
-
- private void destroyDrivingStateManager() {
- try {
- if (mDrivingStateManager != null) {
- mDrivingStateManager.unregisterListener();
- }
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Error unregistering listeners", e);
+ logD("Car Service connected");
+ mDrivingStateManager = (CarDrivingStateManager) car.getCarManager(
+ Car.CAR_DRIVING_STATE_SERVICE);
+ if (mDrivingStateManager != null) {
+ mDrivingStateManager.registerListener(mDrivingStateHandler);
+ mDrivingStateHandler.onDrivingStateChanged(
+ mDrivingStateManager.getCurrentCarDrivingState());
+ } else {
+ Log.e(TAG, "CarDrivingStateService service not available");
}
- }
+ };
private void logD(String message) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 0f7c1ee..31aced0 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -18,6 +18,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.car.Car;
import android.car.trust.CarTrustAgentEnrollmentManager;
import android.car.userlib.CarUserManagerHelper;
import android.content.BroadcastReceiver;
@@ -50,7 +51,7 @@
private final CarStatusBar mStatusBar;
private final Context mContext;
private final UserManager mUserManager;
- private final CarTrustAgentEnrollmentManager mEnrollmentManager;
+ private CarTrustAgentEnrollmentManager mEnrollmentManager;
private CarTrustAgentUnlockDialogHelper mUnlockDialogHelper;
private UserGridRecyclerView.UserRecord mSelectedUser;
private CarUserManagerHelper mCarUserManagerHelper;
@@ -64,13 +65,11 @@
mContext.unregisterReceiver(mUserUnlockReceiver);
}
};
+ private final Car mCar;
-
- public FullscreenUserSwitcher(CarStatusBar statusBar, ViewStub containerStub,
- CarTrustAgentEnrollmentManager enrollmentManager, Context context) {
+ public FullscreenUserSwitcher(CarStatusBar statusBar, ViewStub containerStub, Context context) {
mStatusBar = statusBar;
mParent = containerStub.inflate();
- mEnrollmentManager = enrollmentManager;
mContext = context;
View container = mParent.findViewById(R.id.container);
@@ -86,6 +85,15 @@
mUnlockDialogHelper = new CarTrustAgentUnlockDialogHelper(mContext);
mUserManager = mContext.getSystemService(UserManager.class);
+ mCar = Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
+ (car, ready) -> {
+ if (!ready) {
+ return;
+ }
+ mEnrollmentManager = (CarTrustAgentEnrollmentManager) car
+ .getCarManager(Car.CAR_TRUST_AGENT_ENROLLMENT_SERVICE);
+ });
+
mShortAnimDuration = container.getResources()
.getInteger(android.R.integer.config_shortAnimTime);
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
@@ -201,6 +209,9 @@
}
private boolean hasTrustedDevice(int uid) {
+ if (mEnrollmentManager == null) { // car service not ready, so it cannot be available.
+ return false;
+ }
return !mEnrollmentManager.getEnrolledDeviceInfoForUser(uid).isEmpty();
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java
index 8de1439..a27dd34 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/PowerManagerHelper.java
@@ -18,13 +18,10 @@
import android.annotation.NonNull;
import android.car.Car;
-import android.car.CarNotConnectedException;
+import android.car.Car.CarServiceLifecycleListener;
import android.car.hardware.power.CarPowerManager;
import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.ServiceConnection;
-import android.os.IBinder;
import android.util.Log;
/**
@@ -39,55 +36,30 @@
private Car mCar;
private CarPowerManager mCarPowerManager;
- private final ServiceConnection mCarConnectionListener =
- new ServiceConnection() {
- public void onServiceConnected(ComponentName name, IBinder service) {
- Log.d(TAG, "Car Service connected");
- try {
- mCarPowerManager = (CarPowerManager) mCar.getCarManager(Car.POWER_SERVICE);
- if (mCarPowerManager != null) {
- mCarPowerManager.setListener(mCarPowerStateListener);
- } else {
- Log.e(TAG, "CarPowerManager service not available");
- }
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Car not connected", e);
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- destroyCarPowerManager();
- }
- };
+ private final CarServiceLifecycleListener mCarServiceLifecycleListener;
PowerManagerHelper(Context context, @NonNull CarPowerStateListener listener) {
mContext = context;
mCarPowerStateListener = listener;
+ mCarServiceLifecycleListener = (car, ready) -> {
+ if (!ready) {
+ return;
+ }
+ Log.d(TAG, "Car Service connected");
+ mCarPowerManager = (CarPowerManager) car.getCarManager(Car.POWER_SERVICE);
+ if (mCarPowerManager != null) {
+ mCarPowerManager.setListener(mCarPowerStateListener);
+ } else {
+ Log.e(TAG, "CarPowerManager service not available");
+ }
+ };
}
/**
* Connect to Car service.
*/
void connectToCarService() {
- mCar = Car.createCar(mContext, mCarConnectionListener);
- if (mCar != null) {
- mCar.connect();
- }
- }
-
- /**
- * Disconnects from Car service.
- */
- void disconnectFromCarService() {
- if (mCar != null) {
- mCar.disconnect();
- }
- }
-
- private void destroyCarPowerManager() {
- if (mCarPowerManager != null) {
- mCarPowerManager.clearListener();
- }
+ mCar = Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
+ mCarServiceLifecycleListener);
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
index 05657ff..fb1870a 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/UserGridRecyclerView.java
@@ -19,6 +19,7 @@
import static android.content.DialogInterface.BUTTON_NEGATIVE;
import static android.content.DialogInterface.BUTTON_POSITIVE;
import static android.os.UserManager.DISALLOW_ADD_USER;
+import static android.os.UserManager.SWITCHABILITY_STATUS_OK;
import android.app.ActivityManager;
import android.app.AlertDialog;
@@ -123,10 +124,12 @@
}
private List<UserRecord> createUserRecords(List<UserInfo> userInfoList) {
+ int fgUserId = ActivityManager.getCurrentUser();
+ UserHandle fgUserHandle = UserHandle.of(fgUserId);
List<UserRecord> userRecords = new ArrayList<>();
// If the foreground user CANNOT switch to other users, only display the foreground user.
- if (!mCarUserManagerHelper.canForegroundUserSwitchUsers()) {
+ if (mUserManager.getUserSwitchability(fgUserHandle) != SWITCHABILITY_STATUS_OK) {
userRecords.add(createForegroundUserRecord());
return userRecords;
}
@@ -137,7 +140,7 @@
continue;
}
- boolean isForeground = ActivityManager.getCurrentUser() == userInfo.id;
+ boolean isForeground = fgUserId == userInfo.id;
UserRecord record = new UserRecord(userInfo, false /* isStartGuestSession */,
false /* isAddUser */, isForeground);
userRecords.add(record);
@@ -147,7 +150,6 @@
userRecords.add(createStartGuestUserRecord());
// Add add user record if the foreground user can add users
- UserHandle fgUserHandle = UserHandle.of(ActivityManager.getCurrentUser());
if (!mUserManager.hasUserRestriction(DISALLOW_ADD_USER, fgUserHandle)) {
userRecords.add(createAddUserRecord());
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
index e81be1b..41914d2 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/hvac/HvacController.java
@@ -20,15 +20,13 @@
import static android.car.VehiclePropertyIds.HVAC_TEMPERATURE_DISPLAY_UNITS;
import android.car.Car;
+import android.car.Car.CarServiceLifecycleListener;
import android.car.VehicleUnit;
import android.car.hardware.CarPropertyValue;
import android.car.hardware.hvac.CarHvacManager;
import android.car.hardware.hvac.CarHvacManager.CarHvacEventCallback;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.ServiceConnection;
import android.os.Handler;
-import android.os.IBinder;
import android.util.Log;
import java.util.ArrayList;
@@ -54,6 +52,7 @@
private Car mCar;
private CarHvacManager mHvacManager;
private HashMap<HvacKey, List<TemperatureView>> mTempComponents = new HashMap<>();
+
/**
* Callback for getting changes from {@link CarHvacManager} and setting the UI elements to
* match.
@@ -85,39 +84,17 @@
+ " zone: " + zone);
}
};
- /**
- * If the connection to car service goes away then restart it.
- */
- private final IBinder.DeathRecipient mRestart = new IBinder.DeathRecipient() {
- @Override
- public void binderDied() {
- Log.d(TAG, "Death of HVAC triggering a restart");
- if (mCar != null) {
- mCar.disconnect();
- }
- destroyHvacManager();
- mHandler.postDelayed(() -> mCar.connect(), BIND_TO_HVAC_RETRY_DELAY);
- }
- };
- /**
- * Registers callbacks and initializes components upon connection.
- */
- private ServiceConnection mServiceConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- try {
- service.linkToDeath(mRestart, 0);
- mHvacManager = (CarHvacManager) mCar.getCarManager(Car.HVAC_SERVICE);
- mHvacManager.registerCallback(mHardwareCallback);
- initComponents();
- } catch (Exception e) {
- Log.e(TAG, "Failed to correctly connect to HVAC", e);
- }
- }
- @Override
- public void onServiceDisconnected(ComponentName name) {
- destroyHvacManager();
+ private final CarServiceLifecycleListener mCarServiceLifecycleListener = (car, ready) -> {
+ if (!ready) {
+ return;
+ }
+ try {
+ mHvacManager = (CarHvacManager) car.getCarManager(Car.HVAC_SERVICE);
+ mHvacManager.registerCallback(mHardwareCallback);
+ initComponents();
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to correctly connect to HVAC", e);
}
};
@@ -132,18 +109,8 @@
*/
public void connectToCarService() {
mHandler = new Handler();
- mCar = Car.createCar(mContext, mServiceConnection, mHandler);
- if (mCar != null) {
- // note: this connect call handles the retries
- mCar.connect();
- }
- }
-
- private void destroyHvacManager() {
- if (mHvacManager != null) {
- mHvacManager.unregisterCallback(mHardwareCallback);
- mHvacManager = null;
- }
+ mCar = Car.createCar(mContext, /* handler= */ mHandler, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
+ mCarServiceLifecycleListener);
}
/**
diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index 22c7c7a..09223e8 100644
--- a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -24,12 +24,10 @@
import android.app.Dialog;
import android.app.KeyguardManager;
import android.car.Car;
-import android.car.CarNotConnectedException;
+import android.car.Car.CarServiceLifecycleListener;
import android.car.media.CarAudioManager;
-import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.ServiceConnection;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.Color;
@@ -39,7 +37,6 @@
import android.media.AudioManager;
import android.os.Debug;
import android.os.Handler;
-import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.AttributeSet;
@@ -65,7 +62,6 @@
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
/**
@@ -79,8 +75,6 @@
private static final String XML_TAG_VOLUME_ITEMS = "carVolumeItems";
private static final String XML_TAG_VOLUME_ITEM = "item";
- private static final int HOVERING_TIMEOUT = 16000;
- private static final int NORMAL_TIMEOUT = 3000;
private static final int LISTVIEW_ANIMATION_DURATION_IN_MILLIS = 250;
private static final int DISMISS_DELAY_IN_MILLIS = 50;
private static final int ARROW_FADE_IN_START_DELAY_IN_MILLIS = 100;
@@ -94,12 +88,23 @@
// Volume items in the RecyclerView.
private final List<CarVolumeItem> mCarVolumeLineItems = new ArrayList<>();
private final KeyguardManager mKeyguard;
+ private final int mNormalTimeout;
+ private final int mHoveringTimeout;
+
private Window mWindow;
private CustomDialog mDialog;
private RecyclerView mListView;
private CarVolumeItemAdapter mVolumeItemsAdapter;
private Car mCar;
private CarAudioManager mCarAudioManager;
+ private boolean mHovering;
+ private int mCurrentlyDisplayingGroupId;
+ private int mPreviouslyDisplayingGroupId;
+ private boolean mShowing;
+ private boolean mDismissing;
+ private boolean mExpanded;
+ private View mExpandIcon;
+
private final CarAudioManager.CarVolumeCallback mVolumeChangeCallback =
new CarAudioManager.CarVolumeCallback() {
@Override
@@ -129,6 +134,7 @@
volumeItem.progress = value;
}
if ((flags & AudioManager.FLAG_SHOW_UI) != 0) {
+ mPreviouslyDisplayingGroupId = mCurrentlyDisplayingGroupId;
mCurrentlyDisplayingGroupId = groupId;
mHandler.obtainMessage(H.SHOW,
Events.SHOW_REASON_VOLUME_CHANGED).sendToTarget();
@@ -140,81 +146,47 @@
// ignored
}
};
- private boolean mHovering;
- private int mCurrentlyDisplayingGroupId;
- private boolean mShowing;
- private boolean mDismissing;
- private boolean mExpanded;
- private View mExpandIcon;
- private final ServiceConnection mServiceConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- try {
- mExpanded = false;
- mCarAudioManager = (CarAudioManager) mCar.getCarManager(Car.AUDIO_SERVICE);
- int volumeGroupCount = mCarAudioManager.getVolumeGroupCount();
- // Populates volume slider items from volume groups to UI.
- for (int groupId = 0; groupId < volumeGroupCount; groupId++) {
- VolumeItem volumeItem = getVolumeItemForUsages(
- mCarAudioManager.getUsagesForVolumeGroupId(groupId));
- mAvailableVolumeItems.add(volumeItem);
- // The first one is the default item.
- if (groupId == 0) {
- setuptListItem(0);
- }
- }
- // If list is already initiated, update its content.
- if (mVolumeItemsAdapter != null) {
- mVolumeItemsAdapter.notifyDataSetChanged();
- }
- mCarAudioManager.registerCarVolumeCallback(mVolumeChangeCallback);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Car is not connected!", e);
+ private final CarServiceLifecycleListener mCarServiceLifecycleListener = (car, ready) -> {
+ if (!ready) {
+ return;
+ }
+ mExpanded = false;
+ mCarAudioManager = (CarAudioManager) car.getCarManager(Car.AUDIO_SERVICE);
+ int volumeGroupCount = mCarAudioManager.getVolumeGroupCount();
+ // Populates volume slider items from volume groups to UI.
+ for (int groupId = 0; groupId < volumeGroupCount; groupId++) {
+ VolumeItem volumeItem = getVolumeItemForUsages(
+ mCarAudioManager.getUsagesForVolumeGroupId(groupId));
+ mAvailableVolumeItems.add(volumeItem);
+ // The first one is the default item.
+ if (groupId == 0) {
+ clearAllAndSetupDefaultCarVolumeLineItem(0);
}
}
- /**
- * This does not get called when service is properly disconnected.
- * So we need to also handle cleanups in destroy().
- */
- @Override
- public void onServiceDisconnected(ComponentName name) {
- cleanupAudioManager();
+ // If list is already initiated, update its content.
+ if (mVolumeItemsAdapter != null) {
+ mVolumeItemsAdapter.notifyDataSetChanged();
}
+ mCarAudioManager.registerCarVolumeCallback(mVolumeChangeCallback);
};
- private void setuptListItem(int groupId) {
- mCarVolumeLineItems.clear();
- VolumeItem volumeItem = mAvailableVolumeItems.get(groupId);
- volumeItem.defaultItem = true;
- addCarVolumeListItem(volumeItem, /* volumeGroupId = */ groupId,
- R.drawable.car_ic_keyboard_arrow_down, new ExpandIconListener()
- );
- }
-
public CarVolumeDialogImpl(Context context) {
mContext = context;
mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
- mCar = Car.createCar(mContext, mServiceConnection);
+ mNormalTimeout = mContext.getResources().getInteger(
+ R.integer.car_volume_dialog_display_normal_timeout);
+ mHoveringTimeout = mContext.getResources().getInteger(
+ R.integer.car_volume_dialog_display_hovering_timeout);
}
private static int getSeekbarValue(CarAudioManager carAudioManager, int volumeGroupId) {
- try {
- return carAudioManager.getGroupVolume(volumeGroupId);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Car is not connected!", e);
- }
- return 0;
+ return carAudioManager.getGroupVolume(volumeGroupId);
}
private static int getMaxSeekbarValue(CarAudioManager carAudioManager, int volumeGroupId) {
- try {
- return carAudioManager.getGroupMaxVolume(volumeGroupId);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Car is not connected!", e);
- }
- return 0;
+ return carAudioManager.getGroupMaxVolume(volumeGroupId);
}
/**
@@ -224,18 +196,21 @@
@Override
public void init(int windowType, Callback callback) {
initDialog();
-
- mCar.connect();
+ mCar = Car.createCar(mContext, /* handler= */ null, Car.CAR_WAIT_TIMEOUT_DO_NOT_WAIT,
+ mCarServiceLifecycleListener);
}
@Override
public void destroy() {
- mHandler.removeCallbacksAndMessages(null);
+ mHandler.removeCallbacksAndMessages(/* token= */ null);
cleanupAudioManager();
// unregisterVolumeCallback is not being called when disconnect car, so we manually cleanup
// audio manager beforehand.
- mCar.disconnect();
+ if (mCar != null) {
+ mCar.disconnect();
+ mCar = null;
+ }
}
private void initDialog() {
@@ -303,19 +278,36 @@
mHandler.removeMessages(H.SHOW);
mHandler.removeMessages(H.DISMISS);
+
rescheduleTimeoutH();
+
// Refresh the data set before showing.
mVolumeItemsAdapter.notifyDataSetChanged();
+
if (mShowing) {
+ if (mPreviouslyDisplayingGroupId == mCurrentlyDisplayingGroupId || mExpanded) {
+ return;
+ }
+
+ clearAllAndSetupDefaultCarVolumeLineItem(mCurrentlyDisplayingGroupId);
return;
}
+
mShowing = true;
- setuptListItem(mCurrentlyDisplayingGroupId);
+ clearAllAndSetupDefaultCarVolumeLineItem(mCurrentlyDisplayingGroupId);
mDialog.show();
Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked());
}
- private void rescheduleTimeoutH() {
+ private void clearAllAndSetupDefaultCarVolumeLineItem(int groupId) {
+ mCarVolumeLineItems.clear();
+ VolumeItem volumeItem = mAvailableVolumeItems.get(groupId);
+ volumeItem.defaultItem = true;
+ addCarVolumeListItem(volumeItem, /* volumeGroupId = */ groupId,
+ R.drawable.car_ic_keyboard_arrow_down, new ExpandIconListener());
+ }
+
+ protected void rescheduleTimeoutH() {
mHandler.removeMessages(H.DISMISS);
final int timeout = computeTimeoutH();
mHandler.sendMessageDelayed(mHandler
@@ -327,7 +319,7 @@
}
private int computeTimeoutH() {
- return mHovering ? HOVERING_TIMEOUT : NORMAL_TIMEOUT;
+ return mHovering ? mHoveringTimeout : mNormalTimeout;
}
private void dismissH(int reason) {
@@ -389,12 +381,13 @@
if (XML_TAG_VOLUME_ITEM.equals(parser.getName())) {
TypedArray item = mContext.getResources().obtainAttributes(
attrs, R.styleable.carVolumeItems_item);
- int usage = item.getInt(R.styleable.carVolumeItems_item_usage, -1);
+ int usage = item.getInt(R.styleable.carVolumeItems_item_usage,
+ /* defValue= */ -1);
if (usage >= 0) {
VolumeItem volumeItem = new VolumeItem();
volumeItem.rank = rank;
- volumeItem.icon = item.getResourceId(R.styleable.carVolumeItems_item_icon,
- 0);
+ volumeItem.icon = item.getResourceId(
+ R.styleable.carVolumeItems_item_icon, /* defValue= */ 0);
mVolumeItems.put(usage, volumeItem);
rank++;
}
@@ -419,22 +412,22 @@
return result;
}
- private CarVolumeItem addCarVolumeListItem(VolumeItem volumeItem, int volumeGroupId,
- int supplementalIconId,
+ private CarVolumeItem createCarVolumeListItem(VolumeItem volumeItem, int volumeGroupId,
+ Drawable supplementalIcon, int seekbarProgressValue,
@Nullable View.OnClickListener supplementalIconOnClickListener) {
CarVolumeItem carVolumeItem = new CarVolumeItem();
carVolumeItem.setMax(getMaxSeekbarValue(mCarAudioManager, volumeGroupId));
- int color = mContext.getResources().getColor(R.color.car_volume_dialog_tint);
- int progress = getSeekbarValue(mCarAudioManager, volumeGroupId);
- carVolumeItem.setProgress(progress);
+ carVolumeItem.setProgress(seekbarProgressValue);
carVolumeItem.setOnSeekBarChangeListener(
new CarVolumeDialogImpl.VolumeSeekBarChangeListener(volumeGroupId,
mCarAudioManager));
- Drawable primaryIcon = mContext.getResources().getDrawable(volumeItem.icon);
+ carVolumeItem.setGroupId(volumeGroupId);
+
+ int color = mContext.getColor(R.color.car_volume_dialog_tint);
+ Drawable primaryIcon = mContext.getDrawable(volumeItem.icon);
primaryIcon.mutate().setTint(color);
carVolumeItem.setPrimaryIcon(primaryIcon);
- if (supplementalIconId != 0) {
- Drawable supplementalIcon = mContext.getResources().getDrawable(supplementalIconId);
+ if (supplementalIcon != null) {
supplementalIcon.mutate().setTint(color);
carVolumeItem.setSupplementalIcon(supplementalIcon,
/* showSupplementalIconDivider= */ true);
@@ -443,21 +436,23 @@
carVolumeItem.setSupplementalIcon(/* drawable= */ null,
/* showSupplementalIconDivider= */ false);
}
- carVolumeItem.setGroupId(volumeGroupId);
- mCarVolumeLineItems.add(carVolumeItem);
+
volumeItem.carVolumeItem = carVolumeItem;
- volumeItem.progress = progress;
+ volumeItem.progress = seekbarProgressValue;
+
return carVolumeItem;
}
- private VolumeItem findVolumeItem(CarVolumeItem targetItem) {
- for (int i = 0; i < mVolumeItems.size(); ++i) {
- VolumeItem volumeItem = mVolumeItems.valueAt(i);
- if (volumeItem.carVolumeItem == targetItem) {
- return volumeItem;
- }
- }
- return null;
+ private CarVolumeItem addCarVolumeListItem(VolumeItem volumeItem, int volumeGroupId,
+ int supplementalIconId,
+ @Nullable View.OnClickListener supplementalIconOnClickListener) {
+ int seekbarProgressValue = getSeekbarValue(mCarAudioManager, volumeGroupId);
+ Drawable supplementalIcon = supplementalIconId == 0 ? null : mContext.getDrawable(
+ supplementalIconId);
+ CarVolumeItem carVolumeItem = createCarVolumeListItem(volumeItem, volumeGroupId,
+ supplementalIcon, seekbarProgressValue, supplementalIconOnClickListener);
+ mCarVolumeLineItems.add(carVolumeItem);
+ return carVolumeItem;
}
private void cleanupAudioManager() {
@@ -553,21 +548,15 @@
for (int groupId = 0; groupId < mAvailableVolumeItems.size(); ++groupId) {
if (groupId != mCurrentlyDisplayingGroupId) {
VolumeItem volumeItem = mAvailableVolumeItems.get(groupId);
- addCarVolumeListItem(volumeItem, groupId, 0, null);
+ addCarVolumeListItem(volumeItem, groupId, /* supplementalIconId= */ 0,
+ /* supplementalIconOnClickListener= */ null);
}
}
inAnimator = AnimatorInflater.loadAnimator(
mContext, R.anim.car_arrow_fade_in_rotate_up);
} else {
- // Only keeping the default stream if it is not expended.
- Iterator itr = mCarVolumeLineItems.iterator();
- while (itr.hasNext()) {
- CarVolumeItem carVolumeItem = (CarVolumeItem) itr.next();
- if (carVolumeItem.getGroupId() != mCurrentlyDisplayingGroupId) {
- itr.remove();
- }
- }
+ clearAllAndSetupDefaultCarVolumeLineItem(mCurrentlyDisplayingGroupId);
inAnimator = AnimatorInflater.loadAnimator(
mContext, R.anim.car_arrow_fade_in_rotate_down);
}
@@ -605,18 +594,14 @@
// sent back down again.
return;
}
- try {
- if (mCarAudioManager == null) {
- Log.w(TAG, "Ignoring volume change event because the car isn't connected");
- return;
- }
- mAvailableVolumeItems.get(mVolumeGroupId).progress = progress;
- mAvailableVolumeItems.get(
- mVolumeGroupId).carVolumeItem.setProgress(progress);
- mCarAudioManager.setGroupVolume(mVolumeGroupId, progress, 0);
- } catch (CarNotConnectedException e) {
- Log.e(TAG, "Car is not connected!", e);
+ if (mCarAudioManager == null) {
+ Log.w(TAG, "Ignoring volume change event because the car isn't connected");
+ return;
}
+ mAvailableVolumeItems.get(mVolumeGroupId).progress = progress;
+ mAvailableVolumeItems.get(
+ mVolumeGroupId).carVolumeItem.setProgress(progress);
+ mCarAudioManager.setGroupVolume(mVolumeGroupId, progress, 0);
}
@Override
diff --git a/packages/ExternalStorageProvider/res/values-af/strings.xml b/packages/ExternalStorageProvider/res/values-af/strings.xml
index 96b25a4..b7684a7 100644
--- a/packages/ExternalStorageProvider/res/values-af/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-af/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Eksterne berging"</string>
- <string name="storage_description" msgid="8541974407321172792">"Plaaslike berging"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Interne berging"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumente"</string>
+ <string name="app_label" msgid="748293919008814871">"Eksterne berging"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Plaaslike berging"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Interne berging"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumente"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-am/strings.xml b/packages/ExternalStorageProvider/res/values-am/strings.xml
index f2d308c..49de54d 100644
--- a/packages/ExternalStorageProvider/res/values-am/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-am/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"ውጫዊ ማከማቻ"</string>
- <string name="storage_description" msgid="8541974407321172792">"አካባቢያዊ ማከማቻ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ውስጣዊ ማከማቻ"</string>
- <string name="root_documents" msgid="4051252304075469250">"ሰነዶች"</string>
+ <string name="app_label" msgid="748293919008814871">"ውጫዊ ማከማቻ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"አካባቢያዊ ማከማቻ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ውስጣዊ ማከማቻ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ሰነዶች"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ar/strings.xml b/packages/ExternalStorageProvider/res/values-ar/strings.xml
index a01fc02..878f560 100644
--- a/packages/ExternalStorageProvider/res/values-ar/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ar/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"وحدة تخزين خارجية"</string>
- <string name="storage_description" msgid="8541974407321172792">"التخزين المحلي"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"وحدة تخزين داخلية"</string>
- <string name="root_documents" msgid="4051252304075469250">"مستندات"</string>
+ <string name="app_label" msgid="748293919008814871">"وحدة تخزين خارجية"</string>
+ <string name="storage_description" msgid="9176081505553938524">"التخزين المحلي"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"وحدة تخزين داخلية"</string>
+ <string name="root_documents" msgid="5695037589229175941">"مستندات"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-as/strings.xml b/packages/ExternalStorageProvider/res/values-as/strings.xml
index 278b84e..92bb1aa 100644
--- a/packages/ExternalStorageProvider/res/values-as/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-as/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"বাহ্যিক সঞ্চয়াগাৰ"</string>
- <string name="storage_description" msgid="8541974407321172792">"স্থানীয় সঞ্চয়াগাৰ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"আভ্যন্তৰীণ সঞ্চয়াগাৰ"</string>
- <string name="root_documents" msgid="4051252304075469250">"নথিপত্রসমূহ"</string>
+ <string name="app_label" msgid="748293919008814871">"বাহ্যিক সঞ্চয়াগাৰ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"স্থানীয় সঞ্চয়াগাৰ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"আভ্যন্তৰীণ সঞ্চয়াগাৰ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"নথিপত্রসমূহ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-az/strings.xml b/packages/ExternalStorageProvider/res/values-az/strings.xml
index d8c17ee..605a11a 100644
--- a/packages/ExternalStorageProvider/res/values-az/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-az/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Xarici Yaddaş"</string>
- <string name="storage_description" msgid="8541974407321172792">"Yerli yaddaş"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Daxili yaddaş"</string>
- <string name="root_documents" msgid="4051252304075469250">"Sənədlər"</string>
+ <string name="app_label" msgid="748293919008814871">"Xarici Yaddaş"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Yerli yaddaş"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Daxili yaddaş"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Sənədlər"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml b/packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml
index 235b621..88e34fe 100644
--- a/packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-b+sr+Latn/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Spoljna memorija"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokalni memorijski prostor"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Interna memorija"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
+ <string name="app_label" msgid="748293919008814871">"Spoljna memorija"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokalni memorijski prostor"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Interna memorija"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-be/strings.xml b/packages/ExternalStorageProvider/res/values-be/strings.xml
index 911ff54..07c7da5 100644
--- a/packages/ExternalStorageProvider/res/values-be/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-be/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Вонкавае сховішча"</string>
- <string name="storage_description" msgid="8541974407321172792">"Лакальнае сховішча"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Унутранае сховішча"</string>
- <string name="root_documents" msgid="4051252304075469250">"Дакументы"</string>
+ <string name="app_label" msgid="748293919008814871">"Вонкавае сховішча"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Лакальнае сховішча"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Унутранае сховішча"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Дакументы"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-bg/strings.xml b/packages/ExternalStorageProvider/res/values-bg/strings.xml
index e3b58e4..ca89dc5 100644
--- a/packages/ExternalStorageProvider/res/values-bg/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-bg/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Външно хранилище"</string>
- <string name="storage_description" msgid="8541974407321172792">"Локално хранилище"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Вътрешно хранилище"</string>
- <string name="root_documents" msgid="4051252304075469250">"Документи"</string>
+ <string name="app_label" msgid="748293919008814871">"Външно хранилище"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Локално хранилище"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Вътрешно хранилище"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Документи"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-bn/strings.xml b/packages/ExternalStorageProvider/res/values-bn/strings.xml
index 264d82a..2b7f6ad 100644
--- a/packages/ExternalStorageProvider/res/values-bn/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-bn/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"এক্সটারনাল স্টোরেজ"</string>
- <string name="storage_description" msgid="8541974407321172792">"স্থানীয় স্টোরেজ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ইন্টারনাল স্টোরেজ"</string>
- <string name="root_documents" msgid="4051252304075469250">"দস্তাবেজগুলি"</string>
+ <string name="app_label" msgid="748293919008814871">"এক্সটারনাল স্টোরেজ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"স্থানীয় স্টোরেজ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ইন্টারনাল স্টোরেজ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"দস্তাবেজগুলি"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-bs/strings.xml b/packages/ExternalStorageProvider/res/values-bs/strings.xml
index 1eb3020..2c42df7 100644
--- a/packages/ExternalStorageProvider/res/values-bs/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-bs/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Aplikacija za vanjsku pohranu"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokalna pohrana"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Interna pohrana"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
+ <string name="app_label" msgid="748293919008814871">"Aplikacija za vanjsku pohranu"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokalna pohrana"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Interna pohrana"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ca/strings.xml b/packages/ExternalStorageProvider/res/values-ca/strings.xml
index a67de7d..117a416 100644
--- a/packages/ExternalStorageProvider/res/values-ca/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ca/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Emmagatzematge extern"</string>
- <string name="storage_description" msgid="8541974407321172792">"Emmagatzematge local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Emmagatzematge intern"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
+ <string name="app_label" msgid="748293919008814871">"Emmagatzematge extern"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Emmagatzematge local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Emmagatzematge intern"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-cs/strings.xml b/packages/ExternalStorageProvider/res/values-cs/strings.xml
index b9c54b8..761533d 100644
--- a/packages/ExternalStorageProvider/res/values-cs/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-cs/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Externí úložiště"</string>
- <string name="storage_description" msgid="8541974407321172792">"Místní úložiště"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Interní úložiště"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenty"</string>
+ <string name="app_label" msgid="748293919008814871">"Externí úložiště"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Místní úložiště"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Interní úložiště"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenty"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-da/strings.xml b/packages/ExternalStorageProvider/res/values-da/strings.xml
index 4da1419..9d89c80 100644
--- a/packages/ExternalStorageProvider/res/values-da/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-da/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Ekstern lagerplads"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokalt lager"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Intern lagerplads"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenter"</string>
+ <string name="app_label" msgid="748293919008814871">"Ekstern lagerplads"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokalt lager"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Intern lagerplads"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenter"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-de/strings.xml b/packages/ExternalStorageProvider/res/values-de/strings.xml
index 846152b..cb22276 100644
--- a/packages/ExternalStorageProvider/res/values-de/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-de/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Externer Speicher"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokaler Speicher"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Interner Speicher"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumente"</string>
+ <string name="app_label" msgid="748293919008814871">"Externer Speicher"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokaler Speicher"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Interner Speicher"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumente"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-el/strings.xml b/packages/ExternalStorageProvider/res/values-el/strings.xml
index 1e78e53..02123db 100644
--- a/packages/ExternalStorageProvider/res/values-el/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-el/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Εξωτερικός αποθηκευτικός χώρος"</string>
- <string name="storage_description" msgid="8541974407321172792">"Τοπικός χώρος αποθήκευσης"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Εσωτερικός αποθηκευτικός χώρος"</string>
- <string name="root_documents" msgid="4051252304075469250">"Έγγραφα"</string>
+ <string name="app_label" msgid="748293919008814871">"Εξωτερικός αποθηκευτικός χώρος"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Τοπικός χώρος αποθήκευσης"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Εσωτερικός αποθηκευτικός χώρος"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Έγγραφα"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-en-rAU/strings.xml b/packages/ExternalStorageProvider/res/values-en-rAU/strings.xml
index beaaf0d..b6bdd4a 100644
--- a/packages/ExternalStorageProvider/res/values-en-rAU/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-en-rAU/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"External Storage"</string>
- <string name="storage_description" msgid="8541974407321172792">"Local storage"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Internal storage"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
+ <string name="app_label" msgid="748293919008814871">"External Storage"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Local storage"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Internal storage"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-en-rCA/strings.xml b/packages/ExternalStorageProvider/res/values-en-rCA/strings.xml
index beaaf0d..b6bdd4a 100644
--- a/packages/ExternalStorageProvider/res/values-en-rCA/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-en-rCA/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"External Storage"</string>
- <string name="storage_description" msgid="8541974407321172792">"Local storage"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Internal storage"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
+ <string name="app_label" msgid="748293919008814871">"External Storage"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Local storage"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Internal storage"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-en-rGB/strings.xml b/packages/ExternalStorageProvider/res/values-en-rGB/strings.xml
index beaaf0d..b6bdd4a 100644
--- a/packages/ExternalStorageProvider/res/values-en-rGB/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-en-rGB/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"External Storage"</string>
- <string name="storage_description" msgid="8541974407321172792">"Local storage"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Internal storage"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
+ <string name="app_label" msgid="748293919008814871">"External Storage"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Local storage"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Internal storage"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-en-rIN/strings.xml b/packages/ExternalStorageProvider/res/values-en-rIN/strings.xml
index beaaf0d..b6bdd4a 100644
--- a/packages/ExternalStorageProvider/res/values-en-rIN/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-en-rIN/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"External Storage"</string>
- <string name="storage_description" msgid="8541974407321172792">"Local storage"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Internal storage"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
+ <string name="app_label" msgid="748293919008814871">"External Storage"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Local storage"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Internal storage"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-en-rXC/strings.xml b/packages/ExternalStorageProvider/res/values-en-rXC/strings.xml
index 5034d21..afec109 100644
--- a/packages/ExternalStorageProvider/res/values-en-rXC/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-en-rXC/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"External Storage"</string>
- <string name="storage_description" msgid="8541974407321172792">"Local storage"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Internal storage"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
+ <string name="app_label" msgid="748293919008814871">"External Storage"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Local storage"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Internal storage"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-es-rUS/strings.xml b/packages/ExternalStorageProvider/res/values-es-rUS/strings.xml
index 8262422..39392a5 100644
--- a/packages/ExternalStorageProvider/res/values-es-rUS/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-es-rUS/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Almacenamiento externo"</string>
- <string name="storage_description" msgid="8541974407321172792">"Almacenamiento local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Almacenamiento interno"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
+ <string name="app_label" msgid="748293919008814871">"Almacenamiento externo"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Almacenamiento local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Almacenamiento interno"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-es/strings.xml b/packages/ExternalStorageProvider/res/values-es/strings.xml
index 8262422..39392a5 100644
--- a/packages/ExternalStorageProvider/res/values-es/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-es/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Almacenamiento externo"</string>
- <string name="storage_description" msgid="8541974407321172792">"Almacenamiento local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Almacenamiento interno"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
+ <string name="app_label" msgid="748293919008814871">"Almacenamiento externo"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Almacenamiento local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Almacenamiento interno"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-et/strings.xml b/packages/ExternalStorageProvider/res/values-et/strings.xml
index 095202f..7bc135b 100644
--- a/packages/ExternalStorageProvider/res/values-et/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-et/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Väline talletusruum"</string>
- <string name="storage_description" msgid="8541974407321172792">"Kohalik salvestusruum"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Sisemine salvestusruum"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumendid"</string>
+ <string name="app_label" msgid="748293919008814871">"Väline talletusruum"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Kohalik salvestusruum"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Sisemine salvestusruum"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumendid"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-eu/strings.xml b/packages/ExternalStorageProvider/res/values-eu/strings.xml
index c0e8cdd..fb43894 100644
--- a/packages/ExternalStorageProvider/res/values-eu/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-eu/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Kanpoko memoria"</string>
- <string name="storage_description" msgid="8541974407321172792">"Biltegi lokala"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Barneko memoria"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumentuak"</string>
+ <string name="app_label" msgid="748293919008814871">"Kanpoko memoria"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Biltegi lokala"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Barneko memoria"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumentuak"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-fa/strings.xml b/packages/ExternalStorageProvider/res/values-fa/strings.xml
index 0de4d4d..9eabfd0 100644
--- a/packages/ExternalStorageProvider/res/values-fa/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-fa/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"حافظه خارجی"</string>
- <string name="storage_description" msgid="8541974407321172792">"فضای ذخیرهسازی محلی"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"حافظهٔ داخلی"</string>
- <string name="root_documents" msgid="4051252304075469250">"اسناد"</string>
+ <string name="app_label" msgid="748293919008814871">"حافظه خارجی"</string>
+ <string name="storage_description" msgid="9176081505553938524">"فضای ذخیرهسازی محلی"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"حافظهٔ داخلی"</string>
+ <string name="root_documents" msgid="5695037589229175941">"اسناد"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-fi/strings.xml b/packages/ExternalStorageProvider/res/values-fi/strings.xml
index 6619568..bbb1c4f 100644
--- a/packages/ExternalStorageProvider/res/values-fi/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-fi/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Ulkoinen tallennustila"</string>
- <string name="storage_description" msgid="8541974407321172792">"Paikallinen tallennustila"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Sisäinen tallennustila"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumentit"</string>
+ <string name="app_label" msgid="748293919008814871">"Ulkoinen tallennustila"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Paikallinen tallennustila"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Sisäinen tallennustila"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumentit"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-fr-rCA/strings.xml b/packages/ExternalStorageProvider/res/values-fr-rCA/strings.xml
index e1e8f17..6c07457 100644
--- a/packages/ExternalStorageProvider/res/values-fr-rCA/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-fr-rCA/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Stockage externe"</string>
- <string name="storage_description" msgid="8541974407321172792">"Stockage local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Mémoire de stockage interne"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
+ <string name="app_label" msgid="748293919008814871">"Stockage externe"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Stockage local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Mémoire de stockage interne"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-fr/strings.xml b/packages/ExternalStorageProvider/res/values-fr/strings.xml
index e1e8f17..6c07457 100644
--- a/packages/ExternalStorageProvider/res/values-fr/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-fr/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Stockage externe"</string>
- <string name="storage_description" msgid="8541974407321172792">"Stockage local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Mémoire de stockage interne"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documents"</string>
+ <string name="app_label" msgid="748293919008814871">"Stockage externe"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Stockage local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Mémoire de stockage interne"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documents"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-gl/strings.xml b/packages/ExternalStorageProvider/res/values-gl/strings.xml
index eeb2f51..91d9571 100644
--- a/packages/ExternalStorageProvider/res/values-gl/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-gl/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Almacenamento externo"</string>
- <string name="storage_description" msgid="8541974407321172792">"Almacenamento local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Almacenamento interno"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
+ <string name="app_label" msgid="748293919008814871">"Almacenamento externo"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Almacenamento local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Almacenamento interno"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-gu/strings.xml b/packages/ExternalStorageProvider/res/values-gu/strings.xml
index 3f59dd3..fc9a34d 100644
--- a/packages/ExternalStorageProvider/res/values-gu/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-gu/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"બાહ્ય સંગ્રહ"</string>
- <string name="storage_description" msgid="8541974407321172792">"સ્થાનિક સ્ટોરેજ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"આંતરિક સ્ટોરેજ"</string>
- <string name="root_documents" msgid="4051252304075469250">"દસ્તાવેજો"</string>
+ <string name="app_label" msgid="748293919008814871">"બાહ્ય સંગ્રહ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"સ્થાનિક સ્ટોરેજ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"આંતરિક સ્ટોરેજ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"દસ્તાવેજો"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-hi/strings.xml b/packages/ExternalStorageProvider/res/values-hi/strings.xml
index f424871..76f27ff 100644
--- a/packages/ExternalStorageProvider/res/values-hi/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-hi/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"बाहरी मेमोरी"</string>
- <string name="storage_description" msgid="8541974407321172792">"स्थानीय जगह"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"मोबाइल मेमोरी"</string>
- <string name="root_documents" msgid="4051252304075469250">"दस्तावेज़"</string>
+ <string name="app_label" msgid="748293919008814871">"बाहरी मेमोरी"</string>
+ <string name="storage_description" msgid="9176081505553938524">"स्थानीय जगह"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"मोबाइल मेमोरी"</string>
+ <string name="root_documents" msgid="5695037589229175941">"दस्तावेज़"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-hr/strings.xml b/packages/ExternalStorageProvider/res/values-hr/strings.xml
index 1dd696e..bf0ad0c 100644
--- a/packages/ExternalStorageProvider/res/values-hr/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-hr/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Vanjska pohrana"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokalna pohrana"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Unutarnja pohrana"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
+ <string name="app_label" msgid="748293919008814871">"Vanjska pohrana"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokalna pohrana"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Unutarnja pohrana"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-hu/strings.xml b/packages/ExternalStorageProvider/res/values-hu/strings.xml
index 8201630..021a8bb 100644
--- a/packages/ExternalStorageProvider/res/values-hu/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-hu/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Külső tárhely"</string>
- <string name="storage_description" msgid="8541974407321172792">"Helyi tárhely"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Belső tárhely"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumentumok"</string>
+ <string name="app_label" msgid="748293919008814871">"Külső tárhely"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Helyi tárhely"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Belső tárhely"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumentumok"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-hy/strings.xml b/packages/ExternalStorageProvider/res/values-hy/strings.xml
index b8c2ea7..b846d28 100644
--- a/packages/ExternalStorageProvider/res/values-hy/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-hy/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Արտաքին պահոց"</string>
- <string name="storage_description" msgid="8541974407321172792">"Սարքի հիշողություն"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Ներքին պահոց"</string>
- <string name="root_documents" msgid="4051252304075469250">"Փաստաթղթեր"</string>
+ <string name="app_label" msgid="748293919008814871">"Արտաքին պահոց"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Սարքի հիշողություն"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Ներքին պահոց"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Փաստաթղթեր"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-in/strings.xml b/packages/ExternalStorageProvider/res/values-in/strings.xml
index f91d1a5..950e906 100644
--- a/packages/ExternalStorageProvider/res/values-in/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-in/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Penyimpanan Eksternal"</string>
- <string name="storage_description" msgid="8541974407321172792">"Penyimpanan lokal"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Penyimpanan internal"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumen"</string>
+ <string name="app_label" msgid="748293919008814871">"Penyimpanan Eksternal"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Penyimpanan lokal"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Penyimpanan internal"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumen"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-is/strings.xml b/packages/ExternalStorageProvider/res/values-is/strings.xml
index adaf0d4..cac2edb 100644
--- a/packages/ExternalStorageProvider/res/values-is/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-is/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Ytri geymsla"</string>
- <string name="storage_description" msgid="8541974407321172792">"Staðbundin vistun"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Innbyggð geymsla"</string>
- <string name="root_documents" msgid="4051252304075469250">"Skjöl"</string>
+ <string name="app_label" msgid="748293919008814871">"Ytri geymsla"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Staðbundin vistun"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Innbyggð geymsla"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Skjöl"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-it/strings.xml b/packages/ExternalStorageProvider/res/values-it/strings.xml
index 35ba7f3..3a59bed 100644
--- a/packages/ExternalStorageProvider/res/values-it/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-it/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Archivio esterno"</string>
- <string name="storage_description" msgid="8541974407321172792">"Archiviazione locale"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Memoria interna"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documenti"</string>
+ <string name="app_label" msgid="748293919008814871">"Archivio esterno"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Archiviazione locale"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Memoria interna"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-iw/strings.xml b/packages/ExternalStorageProvider/res/values-iw/strings.xml
index f98f439..3027a40 100644
--- a/packages/ExternalStorageProvider/res/values-iw/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-iw/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"אחסון חיצוני"</string>
- <string name="storage_description" msgid="8541974407321172792">"אחסון מקומי"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"אחסון פנימי"</string>
- <string name="root_documents" msgid="4051252304075469250">"מסמכים"</string>
+ <string name="app_label" msgid="748293919008814871">"אחסון חיצוני"</string>
+ <string name="storage_description" msgid="9176081505553938524">"אחסון מקומי"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"אחסון פנימי"</string>
+ <string name="root_documents" msgid="5695037589229175941">"מסמכים"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ja/strings.xml b/packages/ExternalStorageProvider/res/values-ja/strings.xml
index c1623d4..ad04123 100644
--- a/packages/ExternalStorageProvider/res/values-ja/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ja/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"外部ストレージ"</string>
- <string name="storage_description" msgid="8541974407321172792">"ローカル ストレージ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"内部ストレージ"</string>
- <string name="root_documents" msgid="4051252304075469250">"ドキュメント"</string>
+ <string name="app_label" msgid="748293919008814871">"外部ストレージ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ローカル ストレージ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"内部ストレージ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ドキュメント"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ka/strings.xml b/packages/ExternalStorageProvider/res/values-ka/strings.xml
index 3886efa..e320aca 100644
--- a/packages/ExternalStorageProvider/res/values-ka/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ka/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"გარე მეხსიერება"</string>
- <string name="storage_description" msgid="8541974407321172792">"ადგილობრივი მეხსიერება"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"შიდა მეხსიერება"</string>
- <string name="root_documents" msgid="4051252304075469250">"დოკუმენტები"</string>
+ <string name="app_label" msgid="748293919008814871">"გარე მეხსიერება"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ადგილობრივი მეხსიერება"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"შიდა მეხსიერება"</string>
+ <string name="root_documents" msgid="5695037589229175941">"დოკუმენტები"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-kk/strings.xml b/packages/ExternalStorageProvider/res/values-kk/strings.xml
index f6ad94d..825b2d1 100644
--- a/packages/ExternalStorageProvider/res/values-kk/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-kk/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Сыртқы жад"</string>
- <string name="storage_description" msgid="8541974407321172792">"Жергілікті жад"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Ішкі жад"</string>
- <string name="root_documents" msgid="4051252304075469250">"Құжаттар"</string>
+ <string name="app_label" msgid="748293919008814871">"Сыртқы жад"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Жергілікті жад"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Ішкі жад"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Құжаттар"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-km/strings.xml b/packages/ExternalStorageProvider/res/values-km/strings.xml
index a2bb928..cd87a055 100644
--- a/packages/ExternalStorageProvider/res/values-km/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-km/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"ឧបករណ៍ផ្ទុកខាងក្រៅ"</string>
- <string name="storage_description" msgid="8541974407321172792">"ទំហំផ្ទុកមូលដ្ឋាន"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ឧបករណ៍ផ្ទុកខាងក្នុង"</string>
- <string name="root_documents" msgid="4051252304075469250">"ឯកសារ"</string>
+ <string name="app_label" msgid="748293919008814871">"ឧបករណ៍ផ្ទុកខាងក្រៅ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ទំហំផ្ទុកមូលដ្ឋាន"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ឧបករណ៍ផ្ទុកខាងក្នុង"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ឯកសារ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-kn/strings.xml b/packages/ExternalStorageProvider/res/values-kn/strings.xml
index 2883e06..fe35079 100644
--- a/packages/ExternalStorageProvider/res/values-kn/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-kn/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆ"</string>
- <string name="storage_description" msgid="8541974407321172792">"ಸ್ಥಳೀಯ ಸಂಗ್ರಹಣೆ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ಆಂತರಿಕ ಸಂಗ್ರಹಣೆ"</string>
- <string name="root_documents" msgid="4051252304075469250">"ಡಾಕ್ಯುಮೆಂಟ್ಗಳು"</string>
+ <string name="app_label" msgid="748293919008814871">"ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ಸ್ಥಳೀಯ ಸಂಗ್ರಹಣೆ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ಆಂತರಿಕ ಸಂಗ್ರಹಣೆ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ಡಾಕ್ಯುಮೆಂಟ್ಗಳು"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ko/strings.xml b/packages/ExternalStorageProvider/res/values-ko/strings.xml
index 1fa3189..6a255eb 100644
--- a/packages/ExternalStorageProvider/res/values-ko/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ko/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"외부 저장소"</string>
- <string name="storage_description" msgid="8541974407321172792">"로컬 저장소"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"내부 저장소"</string>
- <string name="root_documents" msgid="4051252304075469250">"문서"</string>
+ <string name="app_label" msgid="748293919008814871">"외부 저장소"</string>
+ <string name="storage_description" msgid="9176081505553938524">"로컬 저장소"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"내부 저장소"</string>
+ <string name="root_documents" msgid="5695037589229175941">"문서"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ky/strings.xml b/packages/ExternalStorageProvider/res/values-ky/strings.xml
index e7e34cb..d11daec 100644
--- a/packages/ExternalStorageProvider/res/values-ky/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ky/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Тышкы сактагыч"</string>
- <string name="storage_description" msgid="8541974407321172792">"Жергиликтүү сактагыч"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Ички сактагыч"</string>
- <string name="root_documents" msgid="4051252304075469250">"Документтер"</string>
+ <string name="app_label" msgid="748293919008814871">"Тышкы сактагыч"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Жергиликтүү сактагыч"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Ички сактагыч"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Документтер"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-lo/strings.xml b/packages/ExternalStorageProvider/res/values-lo/strings.xml
index ba344e3..26f7a6e 100644
--- a/packages/ExternalStorageProvider/res/values-lo/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-lo/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"ບ່ອນຈັດເກັບຂໍ້ມູນພາຍນອກ"</string>
- <string name="storage_description" msgid="8541974407321172792">"ບ່ອນຈັດເກັບຂໍ້ມູນໃນເຄື່ອງ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ບ່ອນຈັດເກັບຂໍ້ມູນພາຍໃນ"</string>
- <string name="root_documents" msgid="4051252304075469250">"ເອກະສານ"</string>
+ <string name="app_label" msgid="748293919008814871">"ບ່ອນຈັດເກັບຂໍ້ມູນພາຍນອກ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ບ່ອນຈັດເກັບຂໍ້ມູນໃນເຄື່ອງ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ບ່ອນຈັດເກັບຂໍ້ມູນພາຍໃນ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ເອກະສານ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-lt/strings.xml b/packages/ExternalStorageProvider/res/values-lt/strings.xml
index a345673..beca24e 100644
--- a/packages/ExternalStorageProvider/res/values-lt/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-lt/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Išorinė atmintinė"</string>
- <string name="storage_description" msgid="8541974407321172792">"Vietinė saugykla"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Vidinė atmintinė"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumentai"</string>
+ <string name="app_label" msgid="748293919008814871">"Išorinė atmintinė"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Vietinė saugykla"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Vidinė atmintinė"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumentai"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-lv/strings.xml b/packages/ExternalStorageProvider/res/values-lv/strings.xml
index a3a3ed8..9e362c4 100644
--- a/packages/ExternalStorageProvider/res/values-lv/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-lv/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Ārējā krātuve"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokālā krātuve"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Iekšējā atmiņa"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
+ <string name="app_label" msgid="748293919008814871">"Ārējā krātuve"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokālā krātuve"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Iekšējā atmiņa"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-mk/strings.xml b/packages/ExternalStorageProvider/res/values-mk/strings.xml
index 5ebf8a6..76c6d91 100644
--- a/packages/ExternalStorageProvider/res/values-mk/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-mk/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Надворешна меморија"</string>
- <string name="storage_description" msgid="8541974407321172792">"Локална меморија"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Внатрешен капацитет"</string>
- <string name="root_documents" msgid="4051252304075469250">"Документи"</string>
+ <string name="app_label" msgid="748293919008814871">"Надворешна меморија"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Локална меморија"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Внатрешен капацитет"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Документи"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ml/strings.xml b/packages/ExternalStorageProvider/res/values-ml/strings.xml
index 2f88c79..fab3f16 100644
--- a/packages/ExternalStorageProvider/res/values-ml/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ml/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"ബാഹ്യ സ്റ്റോറേജ്"</string>
- <string name="storage_description" msgid="8541974407321172792">"ലോക്കൽ സ്റ്റോറേജ്"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ആന്തരിക സ്റ്റോറേജ്"</string>
- <string name="root_documents" msgid="4051252304075469250">"പ്രമാണങ്ങൾ"</string>
+ <string name="app_label" msgid="748293919008814871">"ബാഹ്യ സ്റ്റോറേജ്"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ലോക്കൽ സ്റ്റോറേജ്"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ആന്തരിക സ്റ്റോറേജ്"</string>
+ <string name="root_documents" msgid="5695037589229175941">"പ്രമാണങ്ങൾ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-mn/strings.xml b/packages/ExternalStorageProvider/res/values-mn/strings.xml
index afd5d64..e227b7e 100644
--- a/packages/ExternalStorageProvider/res/values-mn/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-mn/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Гадаад сан"</string>
- <string name="storage_description" msgid="8541974407321172792">"Дотоод сан"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Дотоод сан"</string>
- <string name="root_documents" msgid="4051252304075469250">"Документүүд"</string>
+ <string name="app_label" msgid="748293919008814871">"Гадаад сан"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Дотоод сан"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Дотоод сан"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Документүүд"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-mr/strings.xml b/packages/ExternalStorageProvider/res/values-mr/strings.xml
index 7927440..3059610 100644
--- a/packages/ExternalStorageProvider/res/values-mr/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-mr/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"बाह्य संचयन"</string>
- <string name="storage_description" msgid="8541974407321172792">"स्थानिक स्टोरेज"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"अंतर्गत स्टोरेज"</string>
- <string name="root_documents" msgid="4051252304075469250">"दस्तऐवज"</string>
+ <string name="app_label" msgid="748293919008814871">"बाह्य संचयन"</string>
+ <string name="storage_description" msgid="9176081505553938524">"स्थानिक स्टोरेज"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"अंतर्गत स्टोरेज"</string>
+ <string name="root_documents" msgid="5695037589229175941">"दस्तऐवज"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ms/strings.xml b/packages/ExternalStorageProvider/res/values-ms/strings.xml
index 4196acd..ebc3ce2 100644
--- a/packages/ExternalStorageProvider/res/values-ms/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ms/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Storan Luaran"</string>
- <string name="storage_description" msgid="8541974407321172792">"Storan setempat"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Storan dalaman"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumen"</string>
+ <string name="app_label" msgid="748293919008814871">"Storan Luaran"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Storan setempat"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Storan dalaman"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumen"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-my/strings.xml b/packages/ExternalStorageProvider/res/values-my/strings.xml
index 1c7a276..6078194 100644
--- a/packages/ExternalStorageProvider/res/values-my/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-my/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"ပြင်ပသိုလှောင်ရာပစ္စည်း"</string>
- <string name="storage_description" msgid="8541974407321172792">"စက်တွင်း သိုလှောင်ခန်း"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"စက်တွင်း သိုလှောင်ထားမှု"</string>
- <string name="root_documents" msgid="4051252304075469250">"စာရွက်စာတန်းများ"</string>
+ <string name="app_label" msgid="748293919008814871">"ပြင်ပသိုလှောင်ရာပစ္စည်း"</string>
+ <string name="storage_description" msgid="9176081505553938524">"စက်တွင်း သိုလှောင်ခန်း"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"စက်တွင်း သိုလှောင်ထားမှု"</string>
+ <string name="root_documents" msgid="5695037589229175941">"စာရွက်စာတန်းများ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-nb/strings.xml b/packages/ExternalStorageProvider/res/values-nb/strings.xml
index 979cb30..1992f72 100644
--- a/packages/ExternalStorageProvider/res/values-nb/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-nb/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Ekstern lagring"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokal lagring"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Intern lagring"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenter"</string>
+ <string name="app_label" msgid="748293919008814871">"Ekstern lagring"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokal lagring"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Intern lagring"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenter"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ne/strings.xml b/packages/ExternalStorageProvider/res/values-ne/strings.xml
index bbe9c42..bc8871c 100644
--- a/packages/ExternalStorageProvider/res/values-ne/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ne/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"बाह्य भण्डारण"</string>
- <string name="storage_description" msgid="8541974407321172792">"स्थानीय भण्डारण"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"आन्तरिक भण्डारण"</string>
- <string name="root_documents" msgid="4051252304075469250">"कागजातहरू"</string>
+ <string name="app_label" msgid="748293919008814871">"बाह्य भण्डारण"</string>
+ <string name="storage_description" msgid="9176081505553938524">"स्थानीय भण्डारण"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"आन्तरिक भण्डारण"</string>
+ <string name="root_documents" msgid="5695037589229175941">"कागजातहरू"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-nl/strings.xml b/packages/ExternalStorageProvider/res/values-nl/strings.xml
index cea2e9c..455ea50 100644
--- a/packages/ExternalStorageProvider/res/values-nl/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-nl/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Externe opslag"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokale opslag"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Interne opslag"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documenten"</string>
+ <string name="app_label" msgid="748293919008814871">"Externe opslag"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokale opslag"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Interne opslag"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documenten"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-or/strings.xml b/packages/ExternalStorageProvider/res/values-or/strings.xml
index 5387dc7..ba9b811 100644
--- a/packages/ExternalStorageProvider/res/values-or/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-or/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"ଏକ୍ସଟର୍ନଲ୍ ଷ୍ଟୋରେଜ୍"</string>
- <string name="storage_description" msgid="8541974407321172792">"ଲୋକାଲ୍ ଷ୍ଟୋରେଜ୍"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ଇଣ୍ଟର୍ନଲ୍ ଷ୍ଟୋରେଜ୍"</string>
- <string name="root_documents" msgid="4051252304075469250">"ଡକ୍ୟୁମେଣ୍ଟ"</string>
+ <string name="app_label" msgid="748293919008814871">"ଏକ୍ସଟର୍ନଲ୍ ଷ୍ଟୋରେଜ୍"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ଲୋକାଲ୍ ଷ୍ଟୋରେଜ୍"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ଇଣ୍ଟର୍ନଲ୍ ଷ୍ଟୋରେଜ୍"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ଡକ୍ୟୁମେଣ୍ଟ"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-pa/strings.xml b/packages/ExternalStorageProvider/res/values-pa/strings.xml
index 4e9d777..becd075 100644
--- a/packages/ExternalStorageProvider/res/values-pa/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pa/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"ਬਾਹਰੀ ਸਟੋਰੇਜ"</string>
- <string name="storage_description" msgid="8541974407321172792">"ਸਥਾਨਕ ਸਟੋਰੇਜ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ਅੰਦਰੂਨੀ ਸਟੋਰੇਜ"</string>
- <string name="root_documents" msgid="4051252304075469250">"ਦਸਤਾਵੇਜ਼"</string>
+ <string name="app_label" msgid="748293919008814871">"ਬਾਹਰੀ ਸਟੋਰੇਜ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"ਸਥਾਨਕ ਸਟੋਰੇਜ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ਅੰਦਰੂਨੀ ਸਟੋਰੇਜ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ਦਸਤਾਵੇਜ਼"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-pl/strings.xml b/packages/ExternalStorageProvider/res/values-pl/strings.xml
index f710bad..885f25c 100644
--- a/packages/ExternalStorageProvider/res/values-pl/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pl/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Pamięć zewnętrzna"</string>
- <string name="storage_description" msgid="8541974407321172792">"Pamięć lokalna"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Pamięć wewnętrzna"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenty"</string>
+ <string name="app_label" msgid="748293919008814871">"Pamięć zewnętrzna"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Pamięć lokalna"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Pamięć wewnętrzna"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenty"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-pt-rBR/strings.xml b/packages/ExternalStorageProvider/res/values-pt-rBR/strings.xml
index 96046ad..aa745f1 100644
--- a/packages/ExternalStorageProvider/res/values-pt-rBR/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pt-rBR/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Armazenamento externo"</string>
- <string name="storage_description" msgid="8541974407321172792">"Armazenamento local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Armazenamento interno"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
+ <string name="app_label" msgid="748293919008814871">"Armazenamento externo"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Armazenamento local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Armazenamento interno"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml b/packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml
index 35de8ef..9683b4c 100644
--- a/packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pt-rPT/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Armazenamento externo"</string>
- <string name="storage_description" msgid="8541974407321172792">"Armazenamento local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Armazenamento interno"</string>
- <string name="root_documents" msgid="4051252304075469250">"Docs"</string>
+ <string name="app_label" msgid="748293919008814871">"Armazenamento externo"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Armazenamento local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Armazenamento interno"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Docs"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-pt/strings.xml b/packages/ExternalStorageProvider/res/values-pt/strings.xml
index 96046ad..aa745f1 100644
--- a/packages/ExternalStorageProvider/res/values-pt/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-pt/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Armazenamento externo"</string>
- <string name="storage_description" msgid="8541974407321172792">"Armazenamento local"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Armazenamento interno"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documentos"</string>
+ <string name="app_label" msgid="748293919008814871">"Armazenamento externo"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Armazenamento local"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Armazenamento interno"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documentos"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ro/strings.xml b/packages/ExternalStorageProvider/res/values-ro/strings.xml
index aaa9e41..d060654 100644
--- a/packages/ExternalStorageProvider/res/values-ro/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ro/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Stocare externă"</string>
- <string name="storage_description" msgid="8541974407321172792">"Stocare locală"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Stocare internă"</string>
- <string name="root_documents" msgid="4051252304075469250">"Documente"</string>
+ <string name="app_label" msgid="748293919008814871">"Stocare externă"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Stocare locală"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Stocare internă"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Documente"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ru/strings.xml b/packages/ExternalStorageProvider/res/values-ru/strings.xml
index 222532f..55a7550 100644
--- a/packages/ExternalStorageProvider/res/values-ru/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ru/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Внешний накопитель"</string>
- <string name="storage_description" msgid="8541974407321172792">"Локальное хранилище"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Внутренний накопитель"</string>
- <string name="root_documents" msgid="4051252304075469250">"Документы"</string>
+ <string name="app_label" msgid="748293919008814871">"Внешний накопитель"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Локальное хранилище"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Внутренний накопитель"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Документы"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-si/strings.xml b/packages/ExternalStorageProvider/res/values-si/strings.xml
index 1adebec..deaa65f 100644
--- a/packages/ExternalStorageProvider/res/values-si/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-si/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"බාහිර ආචයනය"</string>
- <string name="storage_description" msgid="8541974407321172792">"පෙදෙසි ආචයනය"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"අභ්යන්තර ආචයනය"</string>
- <string name="root_documents" msgid="4051252304075469250">"ලේඛන"</string>
+ <string name="app_label" msgid="748293919008814871">"බාහිර ආචයනය"</string>
+ <string name="storage_description" msgid="9176081505553938524">"පෙදෙසි ආචයනය"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"අභ්යන්තර ආචයනය"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ලේඛන"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sk/strings.xml b/packages/ExternalStorageProvider/res/values-sk/strings.xml
index f94a726..b51210f 100644
--- a/packages/ExternalStorageProvider/res/values-sk/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sk/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Externý ukladací priestor"</string>
- <string name="storage_description" msgid="8541974407321172792">"Miestne úložisko"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Interné úložisko"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenty"</string>
+ <string name="app_label" msgid="748293919008814871">"Externý ukladací priestor"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Miestne úložisko"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Interné úložisko"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenty"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sl/strings.xml b/packages/ExternalStorageProvider/res/values-sl/strings.xml
index 7992e97..262c2b7 100644
--- a/packages/ExternalStorageProvider/res/values-sl/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sl/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Zunanja shramba"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokalna shramba"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Notranja shramba"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumenti"</string>
+ <string name="app_label" msgid="748293919008814871">"Zunanja shramba"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokalna shramba"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Notranja shramba"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sq/strings.xml b/packages/ExternalStorageProvider/res/values-sq/strings.xml
index f73cff1..2a5c557 100644
--- a/packages/ExternalStorageProvider/res/values-sq/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sq/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Hapësirë e jashtme ruajtjeje"</string>
- <string name="storage_description" msgid="8541974407321172792">"Hapësira ruajtëse lokale"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Hapësira e brendshme ruajtëse"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokumente"</string>
+ <string name="app_label" msgid="748293919008814871">"Hapësirë e jashtme ruajtjeje"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Hapësira ruajtëse lokale"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Hapësira e brendshme ruajtëse"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokumente"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sr/strings.xml b/packages/ExternalStorageProvider/res/values-sr/strings.xml
index 6a7be4c..b44ce18 100644
--- a/packages/ExternalStorageProvider/res/values-sr/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sr/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Спољна меморија"</string>
- <string name="storage_description" msgid="8541974407321172792">"Локални меморијски простор"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Интерна меморија"</string>
- <string name="root_documents" msgid="4051252304075469250">"Документи"</string>
+ <string name="app_label" msgid="748293919008814871">"Спољна меморија"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Локални меморијски простор"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Интерна меморија"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Документи"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sv/strings.xml b/packages/ExternalStorageProvider/res/values-sv/strings.xml
index 103e830..11afb19 100644
--- a/packages/ExternalStorageProvider/res/values-sv/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sv/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Extern lagring"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokal lagring"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Intern lagring"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokument"</string>
+ <string name="app_label" msgid="748293919008814871">"Extern lagring"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokal lagring"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Intern lagring"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokument"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-sw/strings.xml b/packages/ExternalStorageProvider/res/values-sw/strings.xml
index fec928c..94231ff 100644
--- a/packages/ExternalStorageProvider/res/values-sw/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-sw/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Hifadhi ya Nje"</string>
- <string name="storage_description" msgid="8541974407321172792">"Hifadhi ya ndani"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Hifadhi ya ndani"</string>
- <string name="root_documents" msgid="4051252304075469250">"Hati"</string>
+ <string name="app_label" msgid="748293919008814871">"Hifadhi ya Nje"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Hifadhi ya ndani"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Hifadhi ya ndani"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Hati"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ta/strings.xml b/packages/ExternalStorageProvider/res/values-ta/strings.xml
index 5d56940..1f25d9e 100644
--- a/packages/ExternalStorageProvider/res/values-ta/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ta/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"வெளிப்புறச் சேமிப்பிடம்"</string>
- <string name="storage_description" msgid="8541974407321172792">"சாதனச் சேமிப்பகம்"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"அகச் சேமிப்பிடம்"</string>
- <string name="root_documents" msgid="4051252304075469250">"ஆவணங்கள்"</string>
+ <string name="app_label" msgid="748293919008814871">"வெளிப்புறச் சேமிப்பிடம்"</string>
+ <string name="storage_description" msgid="9176081505553938524">"சாதனச் சேமிப்பகம்"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"அகச் சேமிப்பிடம்"</string>
+ <string name="root_documents" msgid="5695037589229175941">"ஆவணங்கள்"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-te/strings.xml b/packages/ExternalStorageProvider/res/values-te/strings.xml
index 97ca29d..773ae0e 100644
--- a/packages/ExternalStorageProvider/res/values-te/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-te/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"బాహ్య నిల్వ"</string>
- <string name="storage_description" msgid="8541974407321172792">"స్థానిక నిల్వ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"అంతర్గత నిల్వ"</string>
- <string name="root_documents" msgid="4051252304075469250">"పత్రాలు"</string>
+ <string name="app_label" msgid="748293919008814871">"బాహ్య నిల్వ"</string>
+ <string name="storage_description" msgid="9176081505553938524">"స్థానిక నిల్వ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"అంతర్గత నిల్వ"</string>
+ <string name="root_documents" msgid="5695037589229175941">"పత్రాలు"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-th/strings.xml b/packages/ExternalStorageProvider/res/values-th/strings.xml
index 3a3304f..570a91a 100644
--- a/packages/ExternalStorageProvider/res/values-th/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-th/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"ที่จัดเก็บข้อมูลภายนอก"</string>
- <string name="storage_description" msgid="8541974407321172792">"พื้นที่เก็บข้อมูลในเครื่อง"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"ที่จัดเก็บข้อมูลภายใน"</string>
- <string name="root_documents" msgid="4051252304075469250">"เอกสาร"</string>
+ <string name="app_label" msgid="748293919008814871">"ที่จัดเก็บข้อมูลภายนอก"</string>
+ <string name="storage_description" msgid="9176081505553938524">"พื้นที่เก็บข้อมูลในเครื่อง"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"ที่จัดเก็บข้อมูลภายใน"</string>
+ <string name="root_documents" msgid="5695037589229175941">"เอกสาร"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-tl/strings.xml b/packages/ExternalStorageProvider/res/values-tl/strings.xml
index 7b66436d6..0a35373 100644
--- a/packages/ExternalStorageProvider/res/values-tl/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-tl/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"External Storage"</string>
- <string name="storage_description" msgid="8541974407321172792">"Lokal na storage"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Internal storage"</string>
- <string name="root_documents" msgid="4051252304075469250">"Mga Dokumento"</string>
+ <string name="app_label" msgid="748293919008814871">"External Storage"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Lokal na storage"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Internal storage"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Mga Dokumento"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-tr/strings.xml b/packages/ExternalStorageProvider/res/values-tr/strings.xml
index 39cd4da..2e35805 100644
--- a/packages/ExternalStorageProvider/res/values-tr/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-tr/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Harici Depolama"</string>
- <string name="storage_description" msgid="8541974407321172792">"Yerel depolama"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Dahili depolama"</string>
- <string name="root_documents" msgid="4051252304075469250">"Dokümanlar"</string>
+ <string name="app_label" msgid="748293919008814871">"Harici Depolama"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Yerel depolama"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Dahili depolama"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Dokümanlar"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-uk/strings.xml b/packages/ExternalStorageProvider/res/values-uk/strings.xml
index 25acf03..f01ad81 100644
--- a/packages/ExternalStorageProvider/res/values-uk/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-uk/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Зовнішня пам’ять"</string>
- <string name="storage_description" msgid="8541974407321172792">"Локальна пам’ять"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Внутрішня пам’ять"</string>
- <string name="root_documents" msgid="4051252304075469250">"Документи"</string>
+ <string name="app_label" msgid="748293919008814871">"Зовнішня пам’ять"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Локальна пам’ять"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Внутрішня пам’ять"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Документи"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-ur/strings.xml b/packages/ExternalStorageProvider/res/values-ur/strings.xml
index c22afd9..1aafdd9 100644
--- a/packages/ExternalStorageProvider/res/values-ur/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-ur/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"بیرونی اسٹوریج"</string>
- <string name="storage_description" msgid="8541974407321172792">"مقامی اسٹوریج"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"داخلی اسٹوریج"</string>
- <string name="root_documents" msgid="4051252304075469250">"دستاویزات"</string>
+ <string name="app_label" msgid="748293919008814871">"بیرونی اسٹوریج"</string>
+ <string name="storage_description" msgid="9176081505553938524">"مقامی اسٹوریج"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"داخلی اسٹوریج"</string>
+ <string name="root_documents" msgid="5695037589229175941">"دستاویزات"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-uz/strings.xml b/packages/ExternalStorageProvider/res/values-uz/strings.xml
index 48f8fed..87ab668 100644
--- a/packages/ExternalStorageProvider/res/values-uz/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-uz/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Tashqi xotira"</string>
- <string name="storage_description" msgid="8541974407321172792">"Mahalliy xotira"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Ichki xotira"</string>
- <string name="root_documents" msgid="4051252304075469250">"Hujjatlar"</string>
+ <string name="app_label" msgid="748293919008814871">"Tashqi xotira"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Mahalliy xotira"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Ichki xotira"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Hujjatlar"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-vi/strings.xml b/packages/ExternalStorageProvider/res/values-vi/strings.xml
index f7479c0..e898d2c 100644
--- a/packages/ExternalStorageProvider/res/values-vi/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-vi/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Bộ nhớ ngoài"</string>
- <string name="storage_description" msgid="8541974407321172792">"Bộ nhớ cục bộ"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Bộ nhớ trong"</string>
- <string name="root_documents" msgid="4051252304075469250">"Tài liệu"</string>
+ <string name="app_label" msgid="748293919008814871">"Bộ nhớ ngoài"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Bộ nhớ cục bộ"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Bộ nhớ trong"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Tài liệu"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-zh-rCN/strings.xml b/packages/ExternalStorageProvider/res/values-zh-rCN/strings.xml
index aa6789f..5be6132 100644
--- a/packages/ExternalStorageProvider/res/values-zh-rCN/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-zh-rCN/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"外部存储设备"</string>
- <string name="storage_description" msgid="8541974407321172792">"本地存储空间"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"内部存储空间"</string>
- <string name="root_documents" msgid="4051252304075469250">"文档"</string>
+ <string name="app_label" msgid="748293919008814871">"外部存储设备"</string>
+ <string name="storage_description" msgid="9176081505553938524">"本地存储空间"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"内部存储空间"</string>
+ <string name="root_documents" msgid="5695037589229175941">"文档"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-zh-rHK/strings.xml b/packages/ExternalStorageProvider/res/values-zh-rHK/strings.xml
index 3458c64..1671796 100644
--- a/packages/ExternalStorageProvider/res/values-zh-rHK/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-zh-rHK/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"外部儲存空間"</string>
- <string name="storage_description" msgid="8541974407321172792">"本機儲存空間"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"內部儲存空間"</string>
- <string name="root_documents" msgid="4051252304075469250">"文件"</string>
+ <string name="app_label" msgid="748293919008814871">"外部儲存空間"</string>
+ <string name="storage_description" msgid="9176081505553938524">"本機儲存空間"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"內部儲存空間"</string>
+ <string name="root_documents" msgid="5695037589229175941">"文件"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-zh-rTW/strings.xml b/packages/ExternalStorageProvider/res/values-zh-rTW/strings.xml
index 3458c64..1671796 100644
--- a/packages/ExternalStorageProvider/res/values-zh-rTW/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-zh-rTW/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"外部儲存空間"</string>
- <string name="storage_description" msgid="8541974407321172792">"本機儲存空間"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"內部儲存空間"</string>
- <string name="root_documents" msgid="4051252304075469250">"文件"</string>
+ <string name="app_label" msgid="748293919008814871">"外部儲存空間"</string>
+ <string name="storage_description" msgid="9176081505553938524">"本機儲存空間"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"內部儲存空間"</string>
+ <string name="root_documents" msgid="5695037589229175941">"文件"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/res/values-zu/strings.xml b/packages/ExternalStorageProvider/res/values-zu/strings.xml
index 96f454b..3878591 100644
--- a/packages/ExternalStorageProvider/res/values-zu/strings.xml
+++ b/packages/ExternalStorageProvider/res/values-zu/strings.xml
@@ -16,8 +16,8 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="7123375275748530234">"Isitoreji sangaphandle"</string>
- <string name="storage_description" msgid="8541974407321172792">"Isitoreji sasendaweni"</string>
- <string name="root_internal_storage" msgid="827844243068584127">"Isitoreji sangaphakathi"</string>
- <string name="root_documents" msgid="4051252304075469250">"Amadokhumenti"</string>
+ <string name="app_label" msgid="748293919008814871">"Isitoreji sangaphandle"</string>
+ <string name="storage_description" msgid="9176081505553938524">"Isitoreji sasendaweni"</string>
+ <string name="root_internal_storage" msgid="4980477711224234931">"Isitoreji sangaphakathi"</string>
+ <string name="root_documents" msgid="5695037589229175941">"Amadokhumenti"</string>
</resources>
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 48d34ae..af96982 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -129,17 +129,17 @@
}
@Override
- protected int enforceReadPermissionInner(Uri uri, String callingPkg, IBinder callerToken)
- throws SecurityException {
+ protected int enforceReadPermissionInner(Uri uri, String callingPkg,
+ @Nullable String featureId, IBinder callerToken) throws SecurityException {
enforceShellRestrictions();
- return super.enforceReadPermissionInner(uri, callingPkg, callerToken);
+ return super.enforceReadPermissionInner(uri, callingPkg, featureId, callerToken);
}
@Override
- protected int enforceWritePermissionInner(Uri uri, String callingPkg, IBinder callerToken)
- throws SecurityException {
+ protected int enforceWritePermissionInner(Uri uri, String callingPkg,
+ @Nullable String featureId, IBinder callerToken) throws SecurityException {
enforceShellRestrictions();
- return super.enforceWritePermissionInner(uri, callingPkg, callerToken);
+ return super.enforceWritePermissionInner(uri, callingPkg, featureId, callerToken);
}
public void updateVolumes() {
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
index 0a37cc6..99f6a92 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/handheld/UninstallAlertDialogFragment.java
@@ -16,7 +16,6 @@
package com.android.packageinstaller.handheld;
-import static android.os.storage.StorageManager.convert;
import static android.text.format.Formatter.formatFileSize;
import android.annotation.NonNull;
@@ -34,8 +33,6 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
-import android.os.storage.StorageManager;
-import android.os.storage.StorageVolume;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -64,29 +61,18 @@
* @return The number of bytes.
*/
private long getAppDataSizeForUser(@NonNull String pkg, @NonNull UserHandle user) {
- StorageManager storageManager = getContext().getSystemService(StorageManager.class);
StorageStatsManager storageStatsManager =
getContext().getSystemService(StorageStatsManager.class);
-
- List<StorageVolume> volumes = storageManager.getStorageVolumes();
- long appDataSize = 0;
-
- int numVolumes = volumes.size();
- for (int i = 0; i < numVolumes; i++) {
- StorageStats stats;
- try {
- stats = storageStatsManager.queryStatsForPackage(convert(volumes.get(i).getUuid()),
- pkg, user);
- } catch (PackageManager.NameNotFoundException | IOException e) {
- Log.e(LOG_TAG, "Cannot determine amount of app data for " + pkg + " on "
- + volumes.get(i) + " (user " + user + ")", e);
- continue;
- }
-
- appDataSize += stats.getDataBytes();
+ try {
+ StorageStats stats = storageStatsManager.queryStatsForPackage(
+ getContext().getPackageManager().getApplicationInfo(pkg, 0).storageUuid,
+ pkg, user);
+ return stats.getDataBytes();
+ } catch (PackageManager.NameNotFoundException | IOException e) {
+ Log.e(LOG_TAG, "Cannot determine amount of app data for " + pkg, e);
}
- return appDataSize;
+ return 0;
}
/**
diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
index c4df2e8..b9daf7f 100644
--- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java
@@ -406,8 +406,8 @@
return null;
}
try {
- return provider.call(context.getPackageName(), uri.getAuthority(),
- method, uri.toString(), bundle);
+ return provider.call(context.getPackageName(), context.getFeatureId(),
+ uri.getAuthority(), method, uri.toString(), bundle);
} catch (RemoteException e) {
return null;
}
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index f25b5eb..843967d 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Middelmatig"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Vinnig"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Baie vinnig"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Ontkoppel"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Ontkoppel tans…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Totdat jy dit afskakel"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Sopas"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Hierdie toestel"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 6332c848..871a7fc 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"መካከለኛ"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"ፈጣን"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"እጅግ በጣም ፈጣን"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"ተለያይቷል"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"በመለያየት ላይ..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"እስኪያጠፉት ድረስ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ልክ አሁን"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"ይህ መሣሪያ"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 8c72527..9ee6322 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"متوسطة"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"سريعة"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"سريعة جدًا"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"غير متصل"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"جارٍ قطع الاتصال..."</string>
@@ -470,4 +472,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"إلى أن توقف الوضع يدويًا"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"للتو"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"هذا الجهاز"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index a7ea1e0..9dcd8ba 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -43,8 +43,7 @@
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$sৰ মাধ্যমেৰে উপলব্ধ"</string>
<string name="tap_to_sign_up" msgid="6449724763052579434">"ছাইন আপ কৰিবলৈ টিপক"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"সংযোজিত, ইণ্টাৰনেট নাই"</string>
- <!-- no translation found for private_dns_broken (7356676011023412490) -->
- <skip />
+ <string name="private_dns_broken" msgid="7356676011023412490">"ব্যক্তিগত DNS ছাৰ্ভাৰ এক্সেছ কৰিব নোৱাৰি"</string>
<string name="wifi_limited_connection" msgid="7717855024753201527">"ইণ্টাৰনেট সংযোগ সীমিত"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"ইণ্টাৰনেট সংযোগ নাই"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"ছাইন ইন কৰা দৰকাৰী"</string>
@@ -62,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"মধ্যমীয়া"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"দ্ৰুত"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"অতি দ্ৰুত"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"সংযোগ বিচ্ছিন্ন কৰা হ’ল"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"সংযোগ বিচ্ছিন্ন কৰি থকা হৈছে…"</string>
@@ -467,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"আপুনি অফ নকৰা পর্যন্ত"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"এই মাত্ৰ"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"এই ডিভাইচটো"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index cb7db78..fda96b4 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Orta"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Sürətli"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Çox Sürətli"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Ayrıldı"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Ayrılır..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Deaktiv edənə qədər"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"İndicə"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Bu cihaz"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 75feb32..4dfbd8e 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Srednja"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Brza"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Veoma brza"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Veza je prekinuta"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Prekidanje veze..."</string>
@@ -467,4 +469,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Dok ne isključite"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Upravo"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Ovaj uređaj"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 677aa24..577c1eb 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Сярэдняя"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Хуткая"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Вельмі хуткая"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Адключана"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Адключэнне..."</string>
@@ -468,4 +470,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Пакуль не выключыце"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Толькі што"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Гэта прылада"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 1620422..1007b38 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Средна"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Бърза"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Много бърза"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Изкл."</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Изключва се..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"До изключване"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Току-що"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Това устройство"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index b1e37a6..a92e8e4 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"মাঝারি"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"দ্রুত"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"খুব দ্রুত"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"ডিসকানেক্ট করা হয়েছে"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"ডিসকানেক্ট হচ্ছে..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"যতক্ষণ না আপনি বন্ধ করছেন"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"এখনই"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"এই ডিভাইস"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 911a831..af7219d 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Srednja brzina"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Brzo"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Veoma brzo"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Isključen"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Prekidanje veze…"</string>
@@ -467,4 +469,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Dok ne isključite"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Upravo"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Ovaj uređaj"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 58c2b67..ad6a131 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Mitjana"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Ràpida"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Molt ràpida"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconnectat"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"S\'està desconnectant..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Fins que no ho desactivis"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Ara mateix"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Aquest dispositiu"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 3c3d5b8..577200c 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Střední"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Rychlá"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Velmi rychlá"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Odpojeno"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Odpojování..."</string>
@@ -468,4 +470,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Dokud tuto funkci nevypnete"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Právě teď"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Toto zařízení"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index bf5d6cf..43bd1f15 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Middel"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Hurtig"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Meget hurtig"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> – <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Afbrudt"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Afbryder ..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Indtil du deaktiverer"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Lige nu"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Denne enhed"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index a6dbd5a..8f6d123 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Mittel"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Schnell"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Sehr schnell"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> – <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Nicht verbunden"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Verbindung wird getrennt..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Bis zur Deaktivierung"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"gerade eben"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Dieses Gerät"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index fdba74a..fcdc410 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Μέτρια"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Γρήγορη"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Πολύ γρήγορη"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Αποσυνδέθηκε"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Αποσύνδεση..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Μέχρι την απενεργοποίηση"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Μόλις τώρα"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Αυτή η συσκευή"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index 581adf8..65b19ee 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Medium"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Fast"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Very fast"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Disconnected"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Disconnecting…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Just now"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"This device"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index 581adf8..65b19ee 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Medium"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Fast"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Very fast"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Disconnected"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Disconnecting…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Just now"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"This device"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index 581adf8..65b19ee 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Medium"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Fast"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Very fast"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Disconnected"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Disconnecting…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Just now"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"This device"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index 581adf8..65b19ee 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Medium"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Fast"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Very fast"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Disconnected"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Disconnecting…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Just now"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"This device"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index e75d7bc..3843085 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -61,6 +61,7 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Medium"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Fast"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Very Fast"</string>
+ <string name="wifi_passpoint_expired" msgid="1711402866023391443">"Expired"</string>
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Disconnected"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Disconnecting…"</string>
@@ -466,4 +467,5 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Until you turn off"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Just now"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"This device"</string>
+ <string name="profile_connect_timeout_subtext" msgid="2401801610868184557">"Problem connecting. Turn device off & back on"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 97cce55..2e1a132 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Media"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Rápida"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Muy rápida"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectado"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Desconectando…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Hasta que lo desactives"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Recién"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Este dispositivo"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 7ba1a94..31ac2a1 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Media"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Rápida"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Muy rápida"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectado"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Desconectando…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Hasta que se desactive"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Justo ahora"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Este dispositivo"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 0e98752..983132a 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Keskmine"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Kiire"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Väga kiire"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Ühendus katkestatud"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Ühenduse katkestamine ..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Kuni välja lülitate"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Äsja"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"See seade"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 872e9a5..727c656 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Tartekoa"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Bizkorra"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Oso bizkorra"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Deskonektatuta"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Deskonektatzen…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Zuk desaktibatu arte"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Oraintxe"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Gailu hau"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 6e281fe..f93af2a 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"متوسط"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"سریع"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"خیلی سریع"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"اتصال قطع شد"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"در حال قطع اتصال..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"تا زمانیکه آن را خاموش کنید"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"هماکنون"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"این دستگاه"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 8c3630a..8550826 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Kohtuullinen"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Nopea"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Hyvin nopea"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Yhteys katkaistu"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Katkaistaan yhteyttä..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Kunnes poistat sen käytöstä"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Äsken"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Tämä laite"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 6c5834a..5c84be7 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Moyenne"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Élevée"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Très rapide"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> : <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Déconnecté"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Déconnexion…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Jusqu\'à la désactivation"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"À l\'instant"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Cet appareil"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 508556e..a6711c7f 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Moyenne"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Élevée"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Très élevée"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Déconnecté"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Déconnexion…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Jusqu\'à la désactivation"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"À l\'instant"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Cet appareil"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 1a3ae3d6..c70c453 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Media"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Rápida"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Moi rápida"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectado"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Desconectando..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Ata a desactivación"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Agora mesmo"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Este dispositivo"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index b3f5185..34a8355a 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"મધ્યમ"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"ઝડપી"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"ખૂબ ઝડપી"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"ડિસ્કનેક્ટ કર્યું"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"ડિસ્કનેક્ટ થઈ રહ્યું છે..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"તમે બંધ ન કરો ત્યાં સુધી"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"હમણાં જ"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"આ ડિવાઇસ"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 454773c..758ce27 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"मध्यम"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"तेज़"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"अत्यधिक तेज़"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"डिसकनेक्ट किया गया"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"डिस्कनेक्ट हो रहा है..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"जब तक आप इसे बंद नहीं करते"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"अभी-अभी"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"यह डिवाइस"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 0ec154b..2f89a66 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Srednje"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Brzo"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Vrlo brzo"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Niste povezani"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Isključivanje…"</string>
@@ -467,4 +469,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Dok ne isključite"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Upravo sad"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Ovaj uređaj"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 4a0af7d..8f6e776 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Közepes"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Gyors"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Nagyon gyors"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Szétkapcsolva"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Szétkapcsolás..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Kikapcsolásig"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Az imént"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Ez az eszköz"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index cc0ecb81..3791b94 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Միջին"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Արագ"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Շատ արագ"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Անջատված է"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Անջատվում է..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Մինչև չանջատեք"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Հենց նոր"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Այս սարքը"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 0733c1f..1a82484 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Sedang"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Cepat"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Sangat Cepat"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Sambungan terputus"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Memutus sambungan..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Sampai Anda menonaktifkannya"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Baru saja"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Perangkat ini"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 28ed8fc..c75e12b 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Miðlungshratt"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Hratt"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Mjög hratt"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Aftengt"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Aftengist…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Þar til þú slekkur"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Rétt í þessu"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Þetta tæki"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index b0569b0..b00d06d 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Media"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Veloce"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Molto veloce"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Disconnesso"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Disconnessione..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Fino alla disattivazione"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Adesso"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Questo dispositivo"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index f7d4fcd..8aeb9af 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -43,8 +43,7 @@
<string name="available_via_passpoint" msgid="1617440946846329613">"זמינה דרך %1$s"</string>
<string name="tap_to_sign_up" msgid="6449724763052579434">"יש להקיש כדי להירשם"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"מחובר. אין אינטרנט"</string>
- <!-- no translation found for private_dns_broken (7356676011023412490) -->
- <skip />
+ <string name="private_dns_broken" msgid="7356676011023412490">"לא ניתן לגשת לשרת DNS הפרטי"</string>
<string name="wifi_limited_connection" msgid="7717855024753201527">"חיבור מוגבל"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"אין אינטרנט"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"נדרשת כניסה"</string>
@@ -62,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"בינונית"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"מהירה"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"מהירה מאוד"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"מנותק"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"מתנתק..."</string>
@@ -469,4 +470,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"עד הכיבוי"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"הרגע"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"המכשיר הזה"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 4d5c86c..bd17074 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"普通"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"速い"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"非常に速い"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"切断"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"切断中..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"OFF にするまで"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"たった今"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"このデバイス"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 20342bc..b1fa87f 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"საშუალო"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"სწრაფი"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"ძალიან სწრაფი"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"კავშირი გაწყვეტილია"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"მიმდინარეობს გათიშვა…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"გამორთვამდე"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ახლახან"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"ეს მოწყობილობა"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 7b6d29e..e4dc6ef 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Орташа"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Жылдам"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Өте жылдам"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Ажыратылған"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Ажыратылуда…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Өшірілгенге дейін"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Дәл қазір"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Осы құрылғы"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index 115be8e..5ca7fe7 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"មធ្យម"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"លឿន"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"លឿនណាស់"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"បានផ្ដាច់"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"កំពុងផ្ដាច់…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"រហូតទាល់តែអ្នកបិទ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"អម្បាញ់មិញ"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"ឧបករណ៍នេះ"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index ac8bfb1..cbdb62c 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -43,8 +43,7 @@
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ಮೂಲಕ ಲಭ್ಯವಿದೆ"</string>
<string name="tap_to_sign_up" msgid="6449724763052579434">"ಸೈನ್ ಅಪ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ, ಇಂಟರ್ನೆಟ್ ಇಲ್ಲ"</string>
- <!-- no translation found for private_dns_broken (7356676011023412490) -->
- <skip />
+ <string name="private_dns_broken" msgid="7356676011023412490">"ಖಾಸಗಿ DNS ಸರ್ವರ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
<string name="wifi_limited_connection" msgid="7717855024753201527">"ಸೀಮಿತ ಸಂಪರ್ಕ"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"ಇಂಟರ್ನೆಟ್ ಇಲ್ಲ"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"ಸೈನ್ ಇನ್ ಮಾಡುವ ಅಗತ್ಯವಿದೆ"</string>
@@ -62,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"ಮಧ್ಯಮ"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"ವೇಗ"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"ತುಂಬಾ ವೇಗವಾಗಿದೆ"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"ಸಂಪರ್ಕ ಕಡಿತಗೊಳಿಸಲಾಗುತ್ತಿದೆ..."</string>
@@ -467,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"ನೀವು ಆಫ್ ಮಾಡುವವರೆಗೆ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ಇದೀಗ"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"ಈ ಸಾಧನ"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 4e54310..9d4a947 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"보통"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"빠름"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"매우 빠름"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"연결 끊김"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"연결을 끊는 중…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"사용 중지할 때까지"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"조금 전"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"이 기기"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index e891b5a..46e002f 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Орто"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Ылдам"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Абдан ылдам"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Ажыратылган"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Ажыратылууда…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Бул функция өчүрүлгөнгө чейин"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Азыр эле"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Ушул түзмөк"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 406a42b..981685e 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"ປານກາງ"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"ໄວ"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"ໄວຫຼາຍ"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"ຕັດການເຊື່ອມຕໍ່ແລ້ວ"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"ກຳລັງຢຸດການເຊື່ອມຕໍ່..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"ຈົນກວ່າທ່ານຈະປິດ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ຕອນນີ້"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"ອຸປະກອນນີ້"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index b305fd90..6d23090 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Vidutinis"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Greitas"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Labai greitas"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Atsijungęs (-usi)"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Atjungiama..."</string>
@@ -468,4 +470,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Kol išjungsite"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Ką tik"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Šis įrenginys"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index c9e2c11..76304e0 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Vidējs"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Ātrs"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Ļoti ātrs"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Atvienots"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Notiek atvienošana..."</string>
@@ -467,4 +469,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Līdz brīdim, kad izslēgsiet"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Tikko"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Šī ierīce"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index e06d414..d0a284a 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Средна"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Брза"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Многу брза"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Исклучено"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Се исклучува..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Додека не го исклучите"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Неодамнешни"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Овој уред"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 36e632a..b5649aa 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"ഇടത്തരം"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"വേഗത്തിൽ"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"വളരെ വേഗത്തിൽ"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"വിച്ഛേദിച്ചു"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"വിച്ഛേദിക്കുന്നു..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"നിങ്ങൾ ഓഫാക്കുന്നത് വരെ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ഇപ്പോൾ"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"ഈ ഉപകരണം"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 1a5a0af..9391142 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Дунд"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Хурдан"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Маш хурдан"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Салгагдсан"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Салгаж байна…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Таныг унтраах хүртэл"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Дөнгөж сая"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Энэ төхөөрөмж"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 7510107..224aa11 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -43,8 +43,7 @@
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s द्वारे उपलब्ध"</string>
<string name="tap_to_sign_up" msgid="6449724763052579434">"साइन अप करण्यासाठी टॅप करा"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"कनेक्ट केले, इंटरनेट नाही"</string>
- <!-- no translation found for private_dns_broken (7356676011023412490) -->
- <skip />
+ <string name="private_dns_broken" msgid="7356676011023412490">"खाजगी DNS सर्व्हर अॅक्सेस करू शकत नाही"</string>
<string name="wifi_limited_connection" msgid="7717855024753201527">"मर्यादित कनेक्शन"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"इंटरनेट नाही"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"साइन इन करणे आवश्यक आहे"</string>
@@ -62,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"मध्यम"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"जलद"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"खूप जलद"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"डिस्कनेक्ट केले"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"डिस्कनेक्ट करत आहे..."</string>
@@ -467,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"तुम्ही बंद करेपर्यंत"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"आत्ताच"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"हे डिव्हाइस"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 82bd697..1c88ba3 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Sederhana"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Laju"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Sangat Laju"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Diputuskan sambungan"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Memutuskan sambungan..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Sehingga anda matikan"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Sebentar tadi"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Peranti ini"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 9636f06..d6a2b93 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"အတော်အသင့်"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"မြန်"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"အလွန်မြန်"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"ချိတ်ဆက်မှုပြတ်တောက်သည်"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"အဆက်အသွယ်ဖြတ်တောက်သည်"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"သင်ပိတ်လိုက်သည် အထိ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ယခုလေးတင်"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"ဤစက်ပစ္စည်း"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 99af7c8..51d84a0 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Middels"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Rask"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Veldig rask"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Frakoblet"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Kobler fra…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Til du slår av"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Nå nettopp"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Denne enheten"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index cdf2c7d..b41b0c7 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"मध्यम"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"छिटो"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"धेरै छिटो"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"विच्छेदन गरियो"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"जडान हटाइँदै ..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"तपाईंले निष्क्रिय नपार्दासम्म"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"अहिले भर्खरै"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"यो यन्त्र"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 709e98d..70d652d 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Gemiddeld"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Snel"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Zeer snel"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Verbinding verbroken"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Verbinding verbreken..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Totdat je uitschakelt"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Zojuist"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Dit apparaat"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index abe0198..c4e0e300 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -43,8 +43,7 @@
<string name="available_via_passpoint" msgid="1617440946846329613">"%1$s ମାଧ୍ୟମରେ ଉପଲବ୍ଧ"</string>
<string name="tap_to_sign_up" msgid="6449724763052579434">"ସାଇନ୍ ଅପ୍ ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"ସଂଯୁକ୍ତ, ଇଣ୍ଟର୍ନେଟ୍ ନାହିଁ"</string>
- <!-- no translation found for private_dns_broken (7356676011023412490) -->
- <skip />
+ <string name="private_dns_broken" msgid="7356676011023412490">"ବ୍ୟକ୍ତିଗତ DNS ସର୍ଭର୍ ଆକ୍ସେସ୍ କରିହେବ ନାହିଁ"</string>
<string name="wifi_limited_connection" msgid="7717855024753201527">"ସୀମିତ ସଂଯୋଗ"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"କୌଣସି ଇଣ୍ଟରନେଟ୍ ନାହିଁ"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"ସାଇନ୍-ଇନ୍ ଆବଶ୍ୟକ"</string>
@@ -62,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"ମଧ୍ୟମ"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"ଦ୍ରୁତ"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"ଅତି ଦ୍ରୁତ"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"ବିଛିନ୍ନ ହେଲା"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"ବିଚ୍ଛିନ୍ନ କରୁଛି…"</string>
@@ -467,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"ଆପଣ ବନ୍ଦ ନକରିବା ପର୍ଯ୍ୟନ୍ତ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ଏହିକ୍ଷଣି"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"ଏହି ଡିଭାଇସ୍"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index b372185..732b78a 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"ਔਸਤ"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"ਤੇਜ਼"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"ਬਹੁਤ ਤੇਜ਼"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"ਡਿਸਕਨੈਕਟ ਕੀਤਾ"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"ਡਿਸਕਨੈਕਟ ਕਰ ਰਿਹਾ ਹੈ..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਬੰਦ ਨਹੀਂ ਕਰਦੇ"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ਹੁਣੇ ਹੀ"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"ਇਹ ਡੀਵਾਈਸ"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index e7a8f22..ce49b75 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -43,8 +43,7 @@
<string name="available_via_passpoint" msgid="1617440946846329613">"Dostępne przez %1$s"</string>
<string name="tap_to_sign_up" msgid="6449724763052579434">"Kliknij, by się zarejestrować"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"Połączono, brak internetu"</string>
- <!-- no translation found for private_dns_broken (7356676011023412490) -->
- <skip />
+ <string name="private_dns_broken" msgid="7356676011023412490">"Brak dostępu do prywatnego serwera DNS"</string>
<string name="wifi_limited_connection" msgid="7717855024753201527">"Ograniczone połączenie"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"Brak internetu"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"Musisz się zalogować"</string>
@@ -62,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Średnia"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Szybka"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Bardzo szybka"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Rozłączona"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Rozłączanie..."</string>
@@ -469,4 +470,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Dopóki nie wyłączysz"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Przed chwilą"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"To urządzenie"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 6e75fba..4b194ec 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Média"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Rápida"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Muito rápida"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectado"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Desconectando…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Até você desativar"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Agora"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Este dispositivo"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 4ee0a17..966ba3f 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Média"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Rápida"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Muito rápida"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Desligado"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"A desligar..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Até ser desativado"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Agora mesmo"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Este dispositivo"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 6e75fba..4b194ec 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Média"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Rápida"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Muito rápida"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Desconectado"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Desconectando…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Até você desativar"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Agora"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Este dispositivo"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index c5725d3..117962d 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Medie"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Rapidă"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Foarte rapidă"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Deconectat"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"În curs de deconectare..."</string>
@@ -467,4 +469,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Până când dezactivați"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Chiar acum"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Acest dispozitiv"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 6e98601..fcbbed9 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Средняя"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Быстрая"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Очень быстрая"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Нет подключения"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Отключение..."</string>
@@ -468,4 +470,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Пока вы не отключите"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Только что"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Это устройство"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 0f67a65..374e5c4 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"මධ්යම"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"වේගවත්"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"ඉතා වේගවත්"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"විසන්ධි වුණි"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"විසන්ධි වෙමින්…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"ඔබ ක්රියාවිරහිත කරන තුරු"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"මේ දැන්"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"මෙම උපාංගය"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index e4b4848..4a660c1 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Stredná"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Vysoká"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Veľmi vysoká"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Odpojený"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Prebieha odpájanie..."</string>
@@ -468,4 +470,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Dokiaľ túto funkciu nevypnete"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Teraz"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Toto zariadenie"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 3e181c2..e806fae 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Srednje hitra"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Hitra"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Zelo hitra"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Prekinjena povezava"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Prekinjanje povezave ..."</string>
@@ -468,4 +470,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Dokler ne izklopite"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"pravkar"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Ta naprava"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 5380302..8aa2917 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Mesatare"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"E shpejtë"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Shumë e shpejtë"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Shkëputur"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Po shkëputet..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Deri sa ta çaktivizosh"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Pikërisht tani"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Kjo pajisje"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index d68c9e8..01c9b80 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Средња"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Брза"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Веома брза"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Веза је прекинута"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Прекидање везе..."</string>
@@ -467,4 +469,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Док не искључите"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Управо"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Овај уређај"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index 45841f0..0f9abc9 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Medelsnabb"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Snabb"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Mycket snabb"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Kopplas ifrån"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Kopplar ifrån…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Tills du inaktiverar funktionen"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Nyss"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Den här enheten"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index a8e73d7..3ccf8a4 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Wastani"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Haraka"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Haraka Sana"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Haijaunganishwa"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Inatenganisha..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Hadi utakapoizima"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Sasa hivi"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Kifaa hiki"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 83fe954..4c6bd22 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"நடுத்தரம்"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"வேகம்"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"மிகவும் வேகமானது"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"தொடர்பு துண்டிக்கப்பட்டது"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"துண்டிக்கிறது..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"ஆஃப் செய்யும் வரை"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"சற்றுமுன்"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"இந்தச் சாதனம்"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index ad0f673..f1f192b 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"మధ్యస్థం"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"వేగవంతం"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"చాలా వేగవంతం"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"డిస్కనెక్ట్ చేయబడింది"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"డిస్కనెక్ట్ చేస్తోంది..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"మీరు ఆఫ్ చేసే వరకు"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ఇప్పుడే"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"ఈ పరికరం"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index c9e232d..e7d7d5b 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"ปานกลาง"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"เร็ว"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"เร็วมาก"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"ตัดการเชื่อมต่อ"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"กำลังตัดการเชื่อมต่อ..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"จนกว่าคุณจะปิด"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"เมื่อสักครู่"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"อุปกรณ์นี้"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 74307f8..a221355 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Katamtaman"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Mabilis"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Napakabilis"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Hindi nakakonekta"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Nadidiskonekta..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Hanggang sa i-off mo"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Ngayon lang"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Ang device na ito"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index b95d941..49aecf8 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Orta"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Hızlı"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Çok Hızlı"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Bağlantı kesildi"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Bağlantı kesiliyor…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Siz kapatana kadar"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Az önce"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Bu cihaz"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 61a0c3e..cf86f4d 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Середня"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Швидка"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Дуже швидка"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>: <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Роз’єднано"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Відключення..."</string>
@@ -468,4 +470,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Доки не вимкнути"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Щойно"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Цей пристрій"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index f21e891..de93a4a 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -43,8 +43,7 @@
<string name="available_via_passpoint" msgid="1617440946846329613">"دستیاب بذریعہ %1$s"</string>
<string name="tap_to_sign_up" msgid="6449724763052579434">"سائن اپ کے لیے تھپتھپائیں"</string>
<string name="wifi_connected_no_internet" msgid="8202906332837777829">"منسلک، انٹرنیٹ نہیں ہے"</string>
- <!-- no translation found for private_dns_broken (7356676011023412490) -->
- <skip />
+ <string name="private_dns_broken" msgid="7356676011023412490">"نجی DNS سرور تک رسائی حاصل نہیں کی جا سکی"</string>
<string name="wifi_limited_connection" msgid="7717855024753201527">"محدود کنکشن"</string>
<string name="wifi_status_no_internet" msgid="5784710974669608361">"انٹرنیٹ نہیں ہے"</string>
<string name="wifi_status_sign_in_required" msgid="123517180404752756">"سائن ان درکار ہے"</string>
@@ -62,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"متوسط"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"تیز"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"بہت تیز"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"منقطع"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"منقطع کیا جارہا ہے…"</string>
@@ -467,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"یہاں تک کہ آپ آف کر دیں"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"ابھی ابھی"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"یہ آلہ"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index a0a79e3..42847e13 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"O‘rtacha"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Tez"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Juda tez"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Uzildi"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Uzilyapti…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Rejimdan chiqilgunicha"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Hozir"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Shu qurilma"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 3723b83..433e924 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Trung bình"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Nhanh"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Rất nhanh"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Đã ngắt kết nối"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Đang ngắt kết nối…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Cho đến khi bạn tắt"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Vừa xong"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Thiết bị này"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index f1200ee..c967372 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"适中"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"快"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"很快"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"已断开连接"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"正在断开连接..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"直到您将其关闭"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"刚刚"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"此设备"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 57ab472..325425c 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"適中"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"快"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"非常快"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g>/<xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"已中斷連線"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"正在中斷連線..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"直至您關閉為止"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"剛剛"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"此裝置"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 630619b..82477ea 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"適中"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"快"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"非常快"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"已中斷連線"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"正在中斷連線…"</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"直到你關閉為止"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"剛剛"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"這個裝置"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index ede336e..d4e8166 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -61,6 +61,8 @@
<string name="speed_label_medium" msgid="3175763313268941953">"Okumaphakathi"</string>
<string name="speed_label_fast" msgid="7715732164050975057">"Sheshayo"</string>
<string name="speed_label_very_fast" msgid="2265363430784523409">"Kushesha kakhulu"</string>
+ <!-- no translation found for wifi_passpoint_expired (1711402866023391443) -->
+ <skip />
<string name="preference_summary_default_combination" msgid="8532964268242666060">"<xliff:g id="STATE">%1$s</xliff:g> / <xliff:g id="DESCRIPTION">%2$s</xliff:g>"</string>
<string name="bluetooth_disconnected" msgid="6557104142667339895">"Ayixhunyiwe"</string>
<string name="bluetooth_disconnecting" msgid="8913264760027764974">"Inqamula uxhumano kwi-inthanethi..."</string>
@@ -466,4 +468,6 @@
<string name="zen_mode_forever" msgid="2704305038191592967">"Uze uvale isikrini"</string>
<string name="time_unit_just_now" msgid="6363336622778342422">"Khona manje"</string>
<string name="media_transfer_this_device_name" msgid="1636276898262571213">"Le divayisi"</string>
+ <!-- no translation found for profile_connect_timeout_subtext (2401801610868184557) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 66e8923..a1ef831 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1186,4 +1186,7 @@
<!-- Name of the this device. [CHAR LIMIT=30] -->
<string name="media_transfer_this_device_name">This device</string>
+
+ <!-- Warning message to tell user is have problem during profile connect, it need to turn off device and back on. [CHAR_LIMIT=NONE] -->
+ <string name="profile_connect_timeout_subtext">Problem connecting. Turn device off & back on</string>
</resources>
diff --git a/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java b/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
index 5dc9061..de45ea5 100644
--- a/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
+++ b/packages/SettingsLib/search/processor-src/com/android/settingslib/search/IndexableProcessor.java
@@ -21,7 +21,6 @@
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
-import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import java.io.IOException;
@@ -73,10 +72,12 @@
}
mRanOnce = true;
+ final ClassName searchIndexableData = ClassName.get(PACKAGE, "SearchIndexableData");
+
final FieldSpec providers = FieldSpec.builder(
ParameterizedTypeName.get(
ClassName.get(Set.class),
- TypeName.get(Class.class)),
+ searchIndexableData),
"mProviders",
Modifier.PRIVATE, Modifier.FINAL)
.initializer("new $T()", HashSet.class)
@@ -84,7 +85,7 @@
final MethodSpec addIndex = MethodSpec.methodBuilder("addIndex")
.addModifiers(Modifier.PUBLIC)
- .addParameter(ClassName.get(Class.class), "indexClass")
+ .addParameter(searchIndexableData, "indexClass")
.addCode("$N.add(indexClass);\n", providers)
.build();
@@ -113,19 +114,25 @@
SearchIndexable searchIndexable = element.getAnnotation(SearchIndexable.class);
int forTarget = searchIndexable.forTarget();
+ MethodSpec.Builder builder = baseConstructorBuilder;
+
if (forTarget == SearchIndexable.ALL) {
- baseConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = baseConstructorBuilder;
} else if ((forTarget & SearchIndexable.MOBILE) != 0) {
- mobileConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = mobileConstructorBuilder;
} else if ((forTarget & SearchIndexable.TV) != 0) {
- tvConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = tvConstructorBuilder;
} else if ((forTarget & SearchIndexable.WEAR) != 0) {
- wearConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = wearConstructorBuilder;
} else if ((forTarget & SearchIndexable.AUTO) != 0) {
- autoConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = autoConstructorBuilder;
} else if ((forTarget & SearchIndexable.ARC) != 0) {
- arcConstructorBuilder.addCode("$N($L.class);\n", addIndex, className);
+ builder = arcConstructorBuilder;
}
+ builder.addCode(
+ "$N(new SearchIndexableData($L.class, $L"
+ + ".SEARCH_INDEX_DATA_PROVIDER));\n",
+ addIndex, className, className);
} else {
throw new IllegalStateException("Null classname from " + element);
}
@@ -137,7 +144,7 @@
.addModifiers(Modifier.PUBLIC)
.returns(ParameterizedTypeName.get(
ClassName.get(Collection.class),
- TypeName.get(Class.class)))
+ searchIndexableData))
.addCode("return $N;\n", providers)
.build();
diff --git a/packages/SettingsLib/search/src/com/android/settingslib/search/Indexable.java b/packages/SettingsLib/search/src/com/android/settingslib/search/Indexable.java
index e68b0d1..8b17ddf 100644
--- a/packages/SettingsLib/search/src/com/android/settingslib/search/Indexable.java
+++ b/packages/SettingsLib/search/src/com/android/settingslib/search/Indexable.java
@@ -56,6 +56,16 @@
List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled);
/**
+ * Return a list of dynamic raw data for indexing. See {@link SearchIndexableRaw}
+ *
+ * @param context the context.
+ * @param enabled hint telling if the data needs to be considered into the search results
+ * or not.
+ * @return a list of {@link SearchIndexableRaw} references. Can be null.
+ */
+ List<SearchIndexableRaw> getDynamicRawDataToIndex(Context context, boolean enabled);
+
+ /**
* Return a list of data keys that cannot be indexed. See {@link SearchIndexableRaw}
*
* @param context the context.
diff --git a/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableData.java b/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableData.java
new file mode 100644
index 0000000..8b8f268
--- /dev/null
+++ b/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableData.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.search;
+
+/**
+ * A Bundle class used in {@link SearchIndexableResources} to provide search Index data.
+ */
+public class SearchIndexableData {
+ private final Class mTargetClass;
+ private final Indexable.SearchIndexProvider mSearchIndexProvider;
+
+ /**
+ * Constructs a SearchIndexableData
+ *
+ * @param targetClass The target opening class of the {@link Indexable.SearchIndexProvider}. It
+ * should be a {@link android.app.Activity} or fragment {@link
+ * androidx.fragment.app.Fragment}.
+ * But fragment is only supported in Android Settings. Other apps should use
+ * {@link android.app.Activity}
+ * @param provider provides searchable data for Android Settings
+ */
+ public SearchIndexableData(Class targetClass, Indexable.SearchIndexProvider provider) {
+ mTargetClass = targetClass;
+ mSearchIndexProvider = provider;
+ }
+
+ public Class getTargetClass() {
+ return mTargetClass;
+ }
+
+ public Indexable.SearchIndexProvider getSearchIndexProvider() {
+ return mSearchIndexProvider;
+ }
+}
diff --git a/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableResources.java b/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableResources.java
index 976647b..e00ca71 100644
--- a/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableResources.java
+++ b/packages/SettingsLib/search/src/com/android/settingslib/search/SearchIndexableResources.java
@@ -21,15 +21,12 @@
public interface SearchIndexableResources {
/**
- * Returns a collection of classes that should be indexed for search.
- *
- * Each class should have the SEARCH_INDEX_DATA_PROVIDER public static member.
+ * Returns a Collection of {@link SearchIndexableData} that should be indexed for search.
*/
- Collection<Class> getProviderValues();
+ Collection<SearchIndexableData> getProviderValues();
/**
- * For testing. Can't use @VisibleForTesting here because this builds as a host binary as well
- * as a device binary.
+ * Add {@link SearchIndexableData} for search in Android Settings.
*/
- void addIndex(Class indexClass);
+ void addIndex(SearchIndexableData indexBundle);
}
\ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 98db7c8..2507a34 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -24,6 +24,9 @@
import android.bluetooth.BluetoothUuid;
import android.content.Context;
import android.content.SharedPreferences;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
import android.os.ParcelUuid;
import android.os.SystemClock;
import android.text.TextUtils;
@@ -55,6 +58,7 @@
// Some Hearing Aids (especially the 2nd device) needs more time to do service discovery
private static final long MAX_HEARING_AIDS_DELAY_FOR_AUTO_CONNECT = 15000;
private static final long MAX_HOGP_DELAY_FOR_AUTO_CONNECT = 30000;
+ private static final long MAX_MEDIA_PROFILE_CONNECT_DELAY = 60000;
private final Context mContext;
private final BluetoothAdapter mLocalAdapter;
@@ -90,9 +94,35 @@
private boolean mIsActiveDeviceA2dp = false;
private boolean mIsActiveDeviceHeadset = false;
private boolean mIsActiveDeviceHearingAid = false;
+ // Media profile connect state
+ private boolean mIsA2dpProfileConnectedFail = false;
+ private boolean mIsHeadsetProfileConnectedFail = false;
+ private boolean mIsHearingAidProfileConnectedFail = false;
// Group second device for Hearing Aid
private CachedBluetoothDevice mSubDevice;
+ private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case BluetoothProfile.A2DP:
+ mIsA2dpProfileConnectedFail = true;
+ break;
+ case BluetoothProfile.HEADSET:
+ mIsHeadsetProfileConnectedFail = true;
+ break;
+ case BluetoothProfile.HEARING_AID:
+ mIsHearingAidProfileConnectedFail = true;
+ break;
+ default:
+ Log.w(TAG, "handleMessage(): unknown message : " + msg.what);
+ break;
+ }
+ Log.w(TAG, "Connect to profile : " + msg.what + " timeout, show error message !");
+ refresh();
+ }
+ };
+
CachedBluetoothDevice(Context context, LocalBluetoothProfileManager profileManager,
BluetoothDevice device) {
mContext = context;
@@ -133,6 +163,35 @@
}
synchronized (mProfileLock) {
+ if (profile instanceof A2dpProfile || profile instanceof HeadsetProfile
+ || profile instanceof HearingAidProfile) {
+ setProfileConnectedStatus(profile.getProfileId(), false);
+ switch (newProfileState) {
+ case BluetoothProfile.STATE_CONNECTED:
+ mHandler.removeMessages(profile.getProfileId());
+ break;
+ case BluetoothProfile.STATE_CONNECTING:
+ mHandler.sendEmptyMessageDelayed(profile.getProfileId(),
+ MAX_MEDIA_PROFILE_CONNECT_DELAY);
+ break;
+ case BluetoothProfile.STATE_DISCONNECTING:
+ if (mHandler.hasMessages(profile.getProfileId())) {
+ mHandler.removeMessages(profile.getProfileId());
+ }
+ break;
+ case BluetoothProfile.STATE_DISCONNECTED:
+ if (mHandler.hasMessages(profile.getProfileId())) {
+ mHandler.removeMessages(profile.getProfileId());
+ setProfileConnectedStatus(profile.getProfileId(), true);
+ }
+ break;
+ default:
+ Log.w(TAG, "onProfileStateChanged(): unknown profile state : "
+ + newProfileState);
+ break;
+ }
+ }
+
if (newProfileState == BluetoothProfile.STATE_CONNECTED) {
if (profile instanceof MapProfile) {
profile.setPreferred(mDevice, true);
@@ -162,6 +221,24 @@
fetchActiveDevices();
}
+ @VisibleForTesting
+ void setProfileConnectedStatus(int profileId, boolean isFailed) {
+ switch (profileId) {
+ case BluetoothProfile.A2DP:
+ mIsA2dpProfileConnectedFail = isFailed;
+ break;
+ case BluetoothProfile.HEADSET:
+ mIsHeadsetProfileConnectedFail = isFailed;
+ break;
+ case BluetoothProfile.HEARING_AID:
+ mIsHearingAidProfileConnectedFail = isFailed;
+ break;
+ default:
+ Log.w(TAG, "setProfileConnectedStatus(): unknown profile id : " + profileId);
+ break;
+ }
+ }
+
public void disconnect() {
synchronized (mProfileLock) {
for (LocalBluetoothProfile profile : mProfiles) {
@@ -844,6 +921,10 @@
int leftBattery = -1;
int rightBattery = -1;
+ if (isProfileConnectedFail() && isConnected()) {
+ return mContext.getString(R.string.profile_connect_timeout_subtext);
+ }
+
synchronized (mProfileLock) {
for (LocalBluetoothProfile profile : getProfiles()) {
int connectionStatus = getProfileConnectionState(profile);
@@ -943,6 +1024,11 @@
return leftBattery >= 0 && rightBattery >= 0;
}
+ private boolean isProfileConnectedFail() {
+ return mIsA2dpProfileConnectedFail || mIsHearingAidProfileConnectedFail
+ || mIsHeadsetProfileConnectedFail;
+ }
+
/**
* @return resource for android auto string that describes the connection state of this device.
*/
diff --git a/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java b/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java
index 4e052f1..69f1c17 100644
--- a/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/utils/ThreadUtils.java
@@ -18,6 +18,7 @@
import android.os.Handler;
import android.os.Looper;
+import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@@ -64,11 +65,16 @@
* @Return A future of the task that can be monitored for updates or cancelled.
*/
public static Future postOnBackgroundThread(Runnable runnable) {
- if (sThreadExecutor == null) {
- sThreadExecutor = Executors.newFixedThreadPool(
- Runtime.getRuntime().availableProcessors());
- }
- return sThreadExecutor.submit(runnable);
+ return getThreadExecutor().submit(runnable);
+ }
+
+ /**
+ * Posts callable in background using shared background thread pool.
+ *
+ * @Return A future of the task that can be monitored for updates or cancelled.
+ */
+ public static Future postOnBackgroundThread(Callable callable) {
+ return getThreadExecutor().submit(callable);
}
/**
@@ -78,4 +84,11 @@
getUiThreadHandler().post(runnable);
}
+ private static synchronized ExecutorService getThreadExecutor() {
+ if (sThreadExecutor == null) {
+ sThreadExecutor = Executors.newFixedThreadPool(
+ Runtime.getRuntime().availableProcessors());
+ }
+ return sThreadExecutor;
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
index 658a0b5..6f19559 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiUtils.java
@@ -93,7 +93,7 @@
if (bssid != null) {
visibility.append(" ").append(bssid);
}
- visibility.append(" technology = ").append(info.getWifiTechnology());
+ visibility.append(" standard = ").append(info.getWifiStandard());
visibility.append(" rssi=").append(info.getRssi());
visibility.append(" ");
visibility.append(" score=").append(info.score);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 93dcbfe..5c89a01 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -21,6 +21,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -31,6 +32,8 @@
import android.content.Context;
import android.media.AudioManager;
+import com.android.settingslib.R;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -922,4 +925,16 @@
assertThat(subCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_1);
assertThat(subCachedDevice.mDevice).isEqualTo(mDevice);
}
+
+ @Test
+ public void getConnectionSummary_profileConnectedFail_showErrorMessage() {
+ final A2dpProfile profle = mock(A2dpProfile.class);
+ mCachedDevice.onProfileStateChanged(profle, BluetoothProfile.STATE_CONNECTED);
+ mCachedDevice.setProfileConnectedStatus(BluetoothProfile.A2DP, true);
+
+ when(profle.getConnectionStatus(mDevice)).thenReturn(BluetoothProfile.STATE_CONNECTED);
+
+ assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
+ mContext.getString(R.string.profile_connect_timeout_subtext));
+ }
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index f7fc0c5..0c3254a 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -228,5 +228,6 @@
VALIDATORS.put(Secure.GLOBAL_ACTIONS_PANEL_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.AWARE_LOCK_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.DISPLAY_DENSITY_FORCED, NON_NEGATIVE_INTEGER_VALIDATOR);
+ VALIDATORS.put(Secure.TAP_GESTURE, BOOLEAN_VALIDATOR);
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
index 8fb879d..1e75fe7 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
@@ -248,7 +248,7 @@
Bundle args = new Bundle();
args.putInt(Settings.CALL_METHOD_USER_KEY,
ActivityManager.getService().getCurrentUser().id);
- Bundle b = provider.call(resolveCallingPackage(), Settings.AUTHORITY,
+ Bundle b = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
Settings.CALL_METHOD_DELETE_CONFIG, compositeKey, args);
success = (b != null && b.getInt(SettingsProvider.RESULT_ROWS_DELETED) == 1);
} catch (RemoteException e) {
@@ -264,7 +264,7 @@
Bundle args = new Bundle();
args.putInt(Settings.CALL_METHOD_USER_KEY,
ActivityManager.getService().getCurrentUser().id);
- Bundle b = provider.call(resolveCallingPackage(), Settings.AUTHORITY,
+ Bundle b = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
Settings.CALL_METHOD_LIST_CONFIG, null, args);
if (b != null) {
Map<String, String> flagsToValues =
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index d28c1aa..55a51da 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -56,8 +56,6 @@
ConfigSettingsProto.CONNECTIVITY_SETTINGS);
namespaceToFieldMap.put(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ConfigSettingsProto.CONTENT_CAPTURE_SETTINGS);
- namespaceToFieldMap.put(DeviceConfig.NAMESPACE_DEX_BOOT,
- ConfigSettingsProto.DEX_BOOT_SETTINGS);
namespaceToFieldMap.put(DeviceConfig.NAMESPACE_GAME_DRIVER,
ConfigSettingsProto.GAME_DRIVER_SETTINGS);
namespaceToFieldMap.put(DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index fdc987f..7765935 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2115,10 +2115,7 @@
}
private static String getSettingPrefix(Bundle args) {
- String prefix = (args != null) ? args.getString(Settings.CALL_METHOD_PREFIX_KEY) : null;
- // Append '/' to ensure we only match properties with this exact prefix.
- // i.e. "foo" should match "foo/property" but not "foobar/property"
- return prefix != null ? prefix + "/" : null;
+ return (args != null) ? args.getString(Settings.CALL_METHOD_PREFIX_KEY) : null;
}
private static boolean getSettingMakeDefault(Bundle args) {
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
index 36360a3..3b3ca5b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsService.java
@@ -309,7 +309,7 @@
try {
Bundle arg = new Bundle();
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
- Bundle result = provider.call(resolveCallingPackage(), Settings.AUTHORITY,
+ Bundle result = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
callListCommand, null, arg);
lines.addAll(result.getStringArrayList(SettingsProvider.RESULT_SETTINGS_LIST));
Collections.sort(lines);
@@ -334,7 +334,7 @@
try {
Bundle arg = new Bundle();
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
- Bundle b = provider.call(resolveCallingPackage(), Settings.AUTHORITY,
+ Bundle b = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
callGetCommand, key, arg);
if (b != null) {
result = b.getPairValue();
@@ -372,7 +372,7 @@
if (makeDefault) {
arg.putBoolean(Settings.CALL_METHOD_MAKE_DEFAULT_KEY, true);
}
- provider.call(resolveCallingPackage(), Settings.AUTHORITY,
+ provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
callPutCommand, key, arg);
} catch (RemoteException e) {
throw new RuntimeException("Failed in IPC", e);
@@ -396,7 +396,7 @@
try {
Bundle arg = new Bundle();
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
- Bundle result = provider.call(resolveCallingPackage(), Settings.AUTHORITY,
+ Bundle result = provider.call(resolveCallingPackage(), null, Settings.AUTHORITY,
callDeleteCommand, key, arg);
return result.getInt(SettingsProvider.RESULT_ROWS_DELETED);
} catch (RemoteException e) {
@@ -423,7 +423,7 @@
}
String packageName = mPackageName != null ? mPackageName : resolveCallingPackage();
arg.putInt(Settings.CALL_METHOD_USER_KEY, userHandle);
- provider.call(packageName, Settings.AUTHORITY, callResetCommand, null, arg);
+ provider.call(packageName, null, Settings.AUTHORITY, callResetCommand, null, arg);
} catch (RemoteException e) {
throw new RuntimeException("Failed in IPC", e);
}
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 9255c87..10d990a 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -732,7 +732,8 @@
Settings.Secure.SILENCE_GESTURE,
Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE,
Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
- Settings.Secure.FACE_UNLOCK_RE_ENROLL);
+ Settings.Secure.FACE_UNLOCK_RE_ENROLL,
+ Settings.Secure.TAP_GESTURE);
@Test
public void systemSettingsBackedUpOrBlacklisted() {
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 54e291f..c59f342 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -180,6 +180,8 @@
<uses-permission android:name="android.permission.MANAGE_WIFI_WHEN_WIRELESS_CONSENT_REQUIRED" />
<!-- Permission needed to invoke DynamicSystem (AOT) -->
<uses-permission android:name="android.permission.INSTALL_DYNAMIC_SYSTEM" />
+ <!-- Used to clean up heap dumps on boot. -->
+ <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
@@ -209,7 +211,7 @@
<!-- Permission required to test ExplicitHealthCheckServiceImpl. -->
<uses-permission android:name="android.permission.BIND_EXPLICIT_HEALTH_CHECK_SERVICE" />
-
+
<!-- Permission required for CTS test - CrossProfileAppsHostSideTest -->
<uses-permission android:name="android.permission.INTERACT_ACROSS_PROFILES"/>
@@ -239,6 +241,11 @@
</intent-filter>
</provider>
+ <provider android:name=".HeapDumpProvider"
+ android:authorities="com.android.shell.heapdump"
+ android:grantUriPermissions="true"
+ android:exported="true" />
+
<activity
android:name=".BugreportWarningActivity"
android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight"
@@ -246,6 +253,14 @@
android:excludeFromRecents="true"
android:exported="false" />
+ <activity android:name=".HeapDumpActivity"
+ android:theme="@*android:style/Theme.Translucent.NoTitleBar"
+ android:label="@*android:string/dump_heap_title"
+ android:finishOnCloseSystemDialogs="true"
+ android:noHistory="true"
+ android:excludeFromRecents="true"
+ android:exported="false" />
+
<receiver
android:name=".BugreportRequestedReceiver"
android:permission="android.permission.TRIGGER_SHELL_BUGREPORT">
@@ -254,6 +269,16 @@
</intent-filter>
</receiver>
+ <receiver
+ android:name=".HeapDumpReceiver"
+ android:permission="android.permission.DUMP">
+ <intent-filter>
+ <action android:name="android.intent.action.BOOT_COMPLETED" />
+ <action android:name="com.android.internal.intent.action.HEAP_DUMP_FINISHED" />
+ <action android:name="com.android.shell.action.DELETE_HEAP_DUMP" />
+ </intent-filter>
+ </receiver>
+
<service
android:name=".BugreportProgressService"
android:exported="false"/>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 1b35770..30ad9c5 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -1560,7 +1560,7 @@
return false;
}
- private static boolean isTv(Context context) {
+ static boolean isTv(Context context) {
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
}
diff --git a/packages/Shell/src/com/android/shell/HeapDumpActivity.java b/packages/Shell/src/com/android/shell/HeapDumpActivity.java
new file mode 100644
index 0000000..0ff0d33
--- /dev/null
+++ b/packages/Shell/src/com/android/shell/HeapDumpActivity.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.shell;
+
+import static com.android.shell.HeapDumpProvider.makeUri;
+import static com.android.shell.HeapDumpReceiver.ACTION_DELETE_HEAP_DUMP;
+import static com.android.shell.HeapDumpReceiver.EXTRA_IS_USER_INITIATED;
+import static com.android.shell.HeapDumpReceiver.EXTRA_PROCESS_NAME;
+import static com.android.shell.HeapDumpReceiver.EXTRA_REPORT_PACKAGE;
+import static com.android.shell.HeapDumpReceiver.EXTRA_SIZE_BYTES;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.AlertDialog;
+import android.content.ActivityNotFoundException;
+import android.content.ClipData;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Process;
+import android.util.DebugUtils;
+import android.util.Log;
+
+import com.android.internal.R;
+
+/**
+ * This activity is displayed when the system has collected a heap dump.
+ */
+public class HeapDumpActivity extends Activity {
+ private static final String TAG = "HeapDumpActivity";
+
+ static final String KEY_URI = "uri";
+
+ private AlertDialog mDialog;
+ private Uri mDumpUri;
+ private boolean mHandled = false;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ String process = getIntent().getStringExtra(EXTRA_PROCESS_NAME);
+ long size = getIntent().getLongExtra(EXTRA_SIZE_BYTES, 0);
+ final boolean isUserInitiated = getIntent().getBooleanExtra(EXTRA_IS_USER_INITIATED, false);
+ final int uid = getIntent().getIntExtra(Intent.EXTRA_UID, 0);
+ final boolean isSystemProcess = uid == Process.SYSTEM_UID;
+ mDumpUri = makeUri(process);
+ final String procDisplayName = isSystemProcess
+ ? getString(com.android.internal.R.string.android_system_label)
+ : process;
+
+ final Intent sendIntent = new Intent();
+ ClipData clip = ClipData.newUri(getContentResolver(), "Heap Dump", mDumpUri);
+ sendIntent.setClipData(clip);
+ sendIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ sendIntent.setType(clip.getDescription().getMimeType(0));
+ sendIntent.putExtra(Intent.EXTRA_STREAM, mDumpUri);
+
+ String directLaunchPackage = getIntent().getStringExtra(EXTRA_REPORT_PACKAGE);
+ if (directLaunchPackage != null) {
+ sendIntent.setAction(ActivityManager.ACTION_REPORT_HEAP_LIMIT);
+ sendIntent.setPackage(directLaunchPackage);
+ try {
+ startActivity(sendIntent);
+ mHandled = true;
+ finish();
+ return;
+ } catch (ActivityNotFoundException e) {
+ Log.e(TAG, "Unable to direct launch to " + directLaunchPackage, e);
+ }
+ }
+
+ final int messageId;
+ if (isUserInitiated) {
+ messageId = com.android.internal.R.string.dump_heap_ready_text;
+ } else if (isSystemProcess) {
+ messageId = com.android.internal.R.string.dump_heap_system_text;
+ } else {
+ messageId = com.android.internal.R.string.dump_heap_text;
+ }
+ mDialog = new AlertDialog.Builder(this, android.R.style.Theme_Material_Light_Dialog_Alert)
+ .setTitle(com.android.internal.R.string.dump_heap_title)
+ .setMessage(getString(messageId, procDisplayName,
+ DebugUtils.sizeValueToString(size, null)))
+ .setNegativeButton(android.R.string.cancel, (dialog, which) -> {
+ mHandled = true;
+ finish();
+ })
+ .setNeutralButton(R.string.delete, (dialog, which) -> {
+ mHandled = true;
+ Intent deleteIntent = new Intent(ACTION_DELETE_HEAP_DUMP);
+ deleteIntent.setClass(getApplicationContext(), HeapDumpReceiver.class);
+ deleteIntent.putExtra(KEY_URI, mDumpUri.toString());
+ sendBroadcast(deleteIntent);
+ finish();
+ })
+ .setPositiveButton(android.R.string.ok, (dialog, which) -> {
+ mHandled = true;
+ sendIntent.setAction(Intent.ACTION_SEND);
+ sendIntent.setPackage(null);
+ startActivity(Intent.createChooser(sendIntent,
+ getText(com.android.internal.R.string.dump_heap_title)));
+ finish();
+ })
+ .show();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ if (!isChangingConfigurations()) {
+ if (!mHandled) {
+ Intent deleteIntent = new Intent(ACTION_DELETE_HEAP_DUMP);
+ deleteIntent.setClass(getApplicationContext(), HeapDumpReceiver.class);
+ deleteIntent.putExtra(KEY_URI, mDumpUri.toString());
+ sendBroadcast(deleteIntent);
+ }
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ }
+}
diff --git a/packages/Shell/src/com/android/shell/HeapDumpProvider.java b/packages/Shell/src/com/android/shell/HeapDumpProvider.java
new file mode 100644
index 0000000..3eceb91
--- /dev/null
+++ b/packages/Shell/src/com/android/shell/HeapDumpProvider.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.shell;
+
+import android.annotation.NonNull;
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.ParcelFileDescriptor;
+import android.os.Process;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/** ContentProvider to write and access heap dumps. */
+public class HeapDumpProvider extends ContentProvider {
+ private static final String FILENAME_SUFFIX = "_javaheap.bin";
+ private static final Object sLock = new Object();
+
+ private File mRoot;
+
+ @Override
+ public boolean onCreate() {
+ synchronized (sLock) {
+ mRoot = new File(getContext().createCredentialProtectedStorageContext().getFilesDir(),
+ "heapdumps");
+ return mRoot.mkdir();
+ }
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ return null;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return "application/octet-stream";
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ throw new UnsupportedOperationException("Insert not allowed.");
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ String path = sanitizePath(uri.getEncodedPath());
+ String tag = Uri.decode(path);
+ return (new File(mRoot, tag)).delete() ? 1 : 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ throw new UnsupportedOperationException("Update not allowed.");
+ }
+
+ @Override
+ public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+ String path = sanitizePath(uri.getEncodedPath());
+ String tag = Uri.decode(path);
+ final int pMode;
+ if (Binder.getCallingUid() == Process.SYSTEM_UID) {
+ pMode = ParcelFileDescriptor.MODE_CREATE
+ | ParcelFileDescriptor.MODE_TRUNCATE
+ | ParcelFileDescriptor.MODE_WRITE_ONLY;
+ } else {
+ pMode = ParcelFileDescriptor.MODE_READ_ONLY;
+ }
+
+ synchronized (sLock) {
+ return ParcelFileDescriptor.open(new File(mRoot, tag), pMode);
+ }
+ }
+
+ @NonNull
+ static Uri makeUri(@NonNull String procName) {
+ return Uri.parse("content://com.android.shell.heapdump/" + procName + FILENAME_SUFFIX);
+ }
+
+ private String sanitizePath(String path) {
+ return path.replaceAll("[^a-zA-Z0-9_.]", "");
+ }
+}
diff --git a/packages/Shell/src/com/android/shell/HeapDumpReceiver.java b/packages/Shell/src/com/android/shell/HeapDumpReceiver.java
new file mode 100644
index 0000000..858c521
--- /dev/null
+++ b/packages/Shell/src/com/android/shell/HeapDumpReceiver.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.shell;
+
+import static com.android.shell.BugreportProgressService.isTv;
+
+import android.annotation.Nullable;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.FileUtils;
+import android.os.Process;
+import android.text.format.DateUtils;
+import android.util.Log;
+
+import java.io.File;
+
+/**
+ * Receiver that handles finished heap dumps.
+ */
+public class HeapDumpReceiver extends BroadcastReceiver {
+ private static final String TAG = "HeapDumpReceiver";
+
+ /**
+ * Broadcast action to determine when to delete a specific dump heap. Must include a {@link
+ * HeapDumpActivity#KEY_URI} String extra.
+ */
+ static final String ACTION_DELETE_HEAP_DUMP = "com.android.shell.action.DELETE_HEAP_DUMP";
+
+ /** Broadcast sent when heap dump collection has been completed. */
+ private static final String ACTION_HEAP_DUMP_FINISHED =
+ "com.android.internal.intent.action.HEAP_DUMP_FINISHED";
+
+ /** The process we are reporting */
+ static final String EXTRA_PROCESS_NAME = "com.android.internal.extra.heap_dump.PROCESS_NAME";
+
+ /** The size limit the process reached. */
+ static final String EXTRA_SIZE_BYTES = "com.android.internal.extra.heap_dump.SIZE_BYTES";
+
+ /** Whether the user initiated the dump or not. */
+ static final String EXTRA_IS_USER_INITIATED =
+ "com.android.internal.extra.heap_dump.IS_USER_INITIATED";
+
+ /** Optional name of package to directly launch. */
+ static final String EXTRA_REPORT_PACKAGE =
+ "com.android.internal.extra.heap_dump.REPORT_PACKAGE";
+
+ private static final String NOTIFICATION_CHANNEL_ID = "heapdumps";
+ private static final int NOTIFICATION_ID = 2019;
+
+ /**
+ * Always keep heap dumps taken in the last week.
+ */
+ private static final long MIN_KEEP_AGE_MS = DateUtils.WEEK_IN_MILLIS;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.d(TAG, "onReceive(): " + intent);
+ final String action = intent.getAction();
+ if (action == null) {
+ Log.e(TAG, "null action received");
+ return;
+ }
+ switch (action) {
+ case Intent.ACTION_BOOT_COMPLETED:
+ cleanupOldFiles(context);
+ break;
+ case ACTION_DELETE_HEAP_DUMP:
+ deleteHeapDump(context, intent.getStringExtra(HeapDumpActivity.KEY_URI));
+ break;
+ case ACTION_HEAP_DUMP_FINISHED:
+ showDumpNotification(context, intent);
+ break;
+ }
+ }
+
+ private void cleanupOldFiles(Context context) {
+ final PendingResult result = goAsync();
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ try {
+ Log.d(TAG, "Deleting from " + new File(context.getFilesDir(), "heapdumps"));
+ FileUtils.deleteOlderFiles(new File(context.getFilesDir(), "heapdumps"), 0,
+ MIN_KEEP_AGE_MS);
+ } catch (RuntimeException e) {
+ Log.e(TAG, "Couldn't delete old files", e);
+ }
+ result.finish();
+ return null;
+ }
+ }.execute();
+ }
+
+ private void deleteHeapDump(Context context, @Nullable final String uri) {
+ if (uri == null) {
+ Log.e(TAG, "null URI for delete heap dump intent");
+ return;
+ }
+ final PendingResult result = goAsync();
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ context.getContentResolver().delete(Uri.parse(uri), null, null);
+ result.finish();
+ return null;
+ }
+ }.execute();
+ }
+
+ private void showDumpNotification(Context context, Intent intent) {
+ final boolean isUserInitiated = intent.getBooleanExtra(
+ EXTRA_IS_USER_INITIATED, false);
+ final String procName = intent.getStringExtra(EXTRA_PROCESS_NAME);
+ final int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
+
+ final String reportPackage = intent.getStringExtra(
+ EXTRA_REPORT_PACKAGE);
+ final long size = intent.getLongExtra(EXTRA_SIZE_BYTES, 0);
+
+ if (procName == null) {
+ Log.e(TAG, "No process name sent over");
+ return;
+ }
+
+ NotificationManager nm = NotificationManager.from(context);
+ nm.createNotificationChannel(
+ new NotificationChannel(NOTIFICATION_CHANNEL_ID,
+ "Heap dumps",
+ NotificationManager.IMPORTANCE_DEFAULT));
+
+ final int titleId = isUserInitiated
+ ? com.android.internal.R.string.dump_heap_ready_notification
+ : com.android.internal.R.string.dump_heap_notification;
+ final String procDisplayName = uid == Process.SYSTEM_UID
+ ? context.getString(com.android.internal.R.string.android_system_label)
+ : procName;
+ String text = context.getString(titleId, procDisplayName);
+
+ Intent shareIntent = new Intent();
+ shareIntent.setClassName(context, HeapDumpActivity.class.getName());
+ shareIntent.putExtra(EXTRA_PROCESS_NAME, procName);
+ shareIntent.putExtra(EXTRA_SIZE_BYTES, size);
+ shareIntent.putExtra(EXTRA_IS_USER_INITIATED, isUserInitiated);
+ shareIntent.putExtra(Intent.EXTRA_UID, uid);
+ if (reportPackage != null) {
+ shareIntent.putExtra(EXTRA_REPORT_PACKAGE, reportPackage);
+ }
+ final Notification.Builder builder = new Notification.Builder(context,
+ NOTIFICATION_CHANNEL_ID)
+ .setSmallIcon(
+ isTv(context) ? R.drawable.ic_bug_report_black_24dp
+ : com.android.internal.R.drawable.stat_sys_adb)
+ .setLocalOnly(true)
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setContentTitle(text)
+ .setTicker(text)
+ .setAutoCancel(true)
+ .setContentText(context.getText(
+ com.android.internal.R.string.dump_heap_notification_detail))
+ .setContentIntent(PendingIntent.getActivity(context, 2, shareIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT));
+
+ Log.v(TAG, "Creating share heap dump notification");
+ NotificationManager.from(context).notify(NOTIFICATION_ID, builder.build());
+ }
+}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index b288eb7..cd64a388 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -60,6 +60,9 @@
<uses-permission android:name="android.permission.GET_APP_OPS_STATS" />
<uses-permission android:name="android.permission.USE_RESERVED_DISK" />
+ <!-- to invoke ContentSuggestionsService -->
+ <uses-permission android:name="android.permission.MANAGE_CONTENT_SUGGESTIONS"/>
+
<!-- Networking and telephony -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
diff --git a/packages/SystemUI/README.md b/packages/SystemUI/README.md
index a3d420e..a4dbf38 100644
--- a/packages/SystemUI/README.md
+++ b/packages/SystemUI/README.md
@@ -80,11 +80,6 @@
Creates/initializes the channels sysui uses when posting notifications.
-### [com.android.systemui.statusbar.CommandQueue$CommandQueueStart](/packages/SystemUI/src/com/android/systemui/sstatusbar/CommandQueue.java)
-
-Creates CommandQueue and calls putComponent because its always been there
-and sysui expects it to be there :/
-
### [com.android.systemui.keyguard.KeyguardViewMediator](/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java)
Manages keyguard view state.
diff --git a/packages/SystemUI/docs/broadcasts.md b/packages/SystemUI/docs/broadcasts.md
new file mode 100644
index 0000000..56a637f
--- /dev/null
+++ b/packages/SystemUI/docs/broadcasts.md
@@ -0,0 +1,89 @@
+# Using SystemUI's BroadcastDispatcher
+
+## What is this dispatcher?
+
+This is an internal dispatcher class for global broadcasts that SystemUI components want to receive. The dispatcher consolidates most `BroadcastReceiver` that exist in SystemUI by merging the `IntentFilter` and subscribing a single `BroadcastReceiver` per user with the system.
+
+## Why use the dispatcher?
+
+Having a single `BroadcastReceiver` in SystemUI improves the multi dispatch situation that occurs whenever many classes are filtering for the same intent action. In particular:
+* All supported `BroadcastReceiver` will be aggregated into one single receiver per user.
+* Whenever there is a broadcast, the number of IPC calls from `system_server` into SystemUI will be reduced to one per user (plus one for `USER_ALL`). This is meaninful for actions that are filtered by `BroadcastReceiver` in multiple classes.
+*There could be more than one per user in the case of unsupported filters.*
+* The dispatcher immediately moves out of the main thread upon broadcast, giving back control to `system_server`. This improves the total dispatch time for broadcasts and prevents from timing out.
+* The dispatcher significantly reduces time spent in main thread by handling most operations in a background thread and only using the main thread for subscribing/unsubscribind and dispatching where appropriate.
+
+## Should I use the dispatcher?
+
+The dispatcher supports `BroadcastReceiver` dynamic subscriptions in the following cases:
+
+* The `IntentFilter` contains at least one action.
+* The `IntentFilter` may or may not contain categories.
+* The `IntentFilter` **does not** contain data types, data schemes, data authorities or data paths.
+* The broadcast **is not** gated behind a permission.
+
+Additionally, the dispatcher supports the following:
+
+* Subscriptions can be done in any thread.
+* Broadcasts will be dispatched on the main thread (same as `system_server`) by default but a `Handler` can be specified for dispatching
+* A `UserHandle` can be provided to filter the broadcasts by user.
+
+If introducing a new `BroadcastReceiver` (not declared in `AndroidManifest`) that satisfies the constraints above, use the dispatcher to reduce the load on `system_server`.
+
+Do not use the dispatcher to obtain the last broadcast (by passing a null `BroadcastReceiver`). `BroadcastDispatcher#registerReceiver` **does not** return the last sticky Intent.
+
+Additionally, if listening to some broadcast is latency critical (beyond 100ms of latency), consider registering with Context instead.
+
+## How do I use the dispatcher?
+
+Acquire the dispatcher by using `@Inject` to obtain a `BroadcastDispatcher`. Then, use the following methods in that instance.
+
+### Subscribe
+
+```kotlin
+/**
+ * Register a receiver for broadcast with the dispatcher
+ *
+ * @param receiver A receiver to dispatch the [Intent]
+ * @param filter A filter to determine what broadcasts should be dispatched to this receiver.
+ * It will only take into account actions and categories for filtering. It must
+ * have at least one action.
+ * @param handler A handler to dispatch [BroadcastReceiver.onReceive]. By default, it is the
+ * main handler. Pass `null` to use the default.
+ * @param user A user handle to determine which broadcast should be dispatched to this receiver.
+ * By default, it is the current user.
+ * @throws IllegalArgumentException if the filter has other constraints that are not actions or
+ * categories or the filter has no actions.
+ */
+@JvmOverloads
+fun registerReceiver(BroadcastReceiver, IntentFilter, Handler? = mainHandler, UserHandle = context.user)
+```
+
+All subscriptions are done with the same overloaded method. As specified in the doc, in order to pass a `UserHandle` with the default `Handler`, pass `null` for the `Handler`.
+
+In the same way as with `Context`, subscribing the same `BroadcastReceiver` for the same user using different filters will result on two subscriptions, not in replacing the filter.
+
+### Unsubscribe
+
+There are two methods to unsubscribe a given `BroadcastReceiver`. One that will remove it for all users and another where the user can be specified. This allows using separate subscriptions of the same receiver for different users and manipulating them separately.
+
+```kotlin
+/**
+ * Unregister receiver for all users.
+ * <br>
+ * This will remove every registration of [receiver], not those done just with [UserHandle.ALL].
+ *
+ * @param receiver The receiver to unregister. It will be unregistered for all users.
+ */
+fun unregisterReceiver(BroadcastReceiver)
+
+/**
+ * Unregister receiver for a particular user.
+ *
+ * @param receiver The receiver to unregister. It will be unregistered for all users.
+ * @param user The user associated to the registered [receiver]. It can be [UserHandle.ALL].
+ */
+fun unregisterReceiverForUser(BroadcastReceiver, UserHandle)
+```
+
+Unregistering can be done even if the `BroadcastReceiver` has never been registered with `BroadcastDispatcher`. In that case, it is a No-Op.
diff --git a/packages/SystemUI/plugin/ExamplePlugin/AndroidManifest.xml b/packages/SystemUI/plugin/ExamplePlugin/AndroidManifest.xml
index ff89bbc..e9e8441 100644
--- a/packages/SystemUI/plugin/ExamplePlugin/AndroidManifest.xml
+++ b/packages/SystemUI/plugin/ExamplePlugin/AndroidManifest.xml
@@ -22,14 +22,16 @@
<application>
<activity android:name=".PluginSettings"
- android:label="@string/plugin_label">
+ android:label="@string/plugin_label"
+ android:exported="false">
<intent-filter>
<action android:name="com.android.systemui.action.PLUGIN_SETTINGS" />
</intent-filter>
</activity>
<service android:name=".SampleOverlayPlugin"
- android:label="@string/plugin_label">
+ android:label="@string/plugin_label"
+ android:exported="false">
<intent-filter>
<action android:name="com.android.systemui.action.PLUGIN_OVERLAY" />
</intent-filter>
diff --git a/packages/SystemUI/res/layout/home_controls.xml b/packages/SystemUI/res/layout/home_controls.xml
index b9a6a48..69a0e87 100644
--- a/packages/SystemUI/res/layout/home_controls.xml
+++ b/packages/SystemUI/res/layout/home_controls.xml
@@ -3,7 +3,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/home_controls_layout"
android:layout_width="match_parent"
- android:layout_height="125dp"
+ android:layout_height="wrap_content"
android:layout_gravity="@integer/notification_panel_layout_gravity"
android:visibility="gone"
android:padding="8dp"
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml b/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml
index 7d6ff3b1..69beffe 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_plugin_frame.xml
@@ -20,7 +20,7 @@
android:id="@+id/plugin_frame"
android:theme="@style/qs_theme"
android:layout_width="@dimen/qs_panel_width"
- android:layout_height="105dp"
+ android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/notification_side_paddings"
android:layout_marginLeft="@dimen/notification_side_paddings"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index efcc2c4..dff21cf 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -274,7 +274,6 @@
<!-- SystemUI Services: The classes of the stuff to start. -->
<string-array name="config_systemUIServiceComponents" translatable="false">
<item>com.android.systemui.util.NotificationChannels</item>
- <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
<item>com.android.systemui.keyguard.KeyguardViewMediator</item>
<item>com.android.systemui.recents.Recents</item>
<item>com.android.systemui.volume.VolumeUI</item>
@@ -483,4 +482,7 @@
<!-- Whether or not to add a "people" notifications section -->
<bool name="config_usePeopleFiltering">false</bool>
+ <!-- Package name for controls plugin -->
+ <string name="config_controlsPluginPackageName" translatable="false">com.android.systemui.controls.panel</string>
+
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 14371fe..64b2892 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1120,8 +1120,6 @@
<dimen name="bubble_touch_padding">12dp</dimen>
<!-- Size of the circle around the bubbles when they're in the dismiss target. -->
<dimen name="bubble_dismiss_encircle_size">52dp</dimen>
- <!-- How much to inset the icon in the circle -->
- <dimen name="bubble_icon_inset">16dp</dimen>
<!-- Padding around the view displayed when the bubble is expanded -->
<dimen name="bubble_expanded_view_padding">4dp</dimen>
<!-- This should be at least the size of bubble_expanded_view_padding; it is used to include
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
index 6186589..5f92b28 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListener.java
@@ -89,6 +89,14 @@
onTaskMovedToFront(taskInfo.taskId);
}
+ /**
+ * Called when a task’s description is changed due to an activity calling
+ * ActivityManagerService.setTaskDescription
+ *
+ * @param taskInfo info about the task which changed, with {@link TaskInfo#taskDescription}
+ */
+ public void onTaskDescriptionChanged(RunningTaskInfo taskInfo) { }
+
public void onActivityRequestedOrientationChanged(int taskId, int requestedOrientation) { }
public void onSizeCompatModeActivityChanged(int displayId, IBinder activityToken) { }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
index 8d823ca..acce41c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TaskStackChangeListeners.java
@@ -56,7 +56,9 @@
}
public void addListener(IActivityManager am, TaskStackChangeListener listener) {
- mTaskStackListeners.add(listener);
+ synchronized (mTaskStackListeners) {
+ mTaskStackListeners.add(listener);
+ }
if (!mRegistered) {
// Register mTaskStackListener to IActivityManager only once if needed.
try {
@@ -69,8 +71,12 @@
}
public void removeListener(TaskStackChangeListener listener) {
- mTaskStackListeners.remove(listener);
- if (mTaskStackListeners.isEmpty() && mRegistered) {
+ boolean isEmpty;
+ synchronized (mTaskStackListeners) {
+ mTaskStackListeners.remove(listener);
+ isEmpty = mTaskStackListeners.isEmpty();
+ }
+ if (isEmpty && mRegistered) {
// Unregister mTaskStackListener once we have no more listeners
try {
ActivityTaskManager.getService().unregisterTaskStackListener(this);
@@ -83,14 +89,17 @@
@Override
public void onTaskStackChanged() throws RemoteException {
- // Call the task changed callback for the non-ui thread listeners first
+ // Call the task changed callback for the non-ui thread listeners first. Copy to a set of
+ // temp listeners so that we don't lock on mTaskStackListeners while calling all the
+ // callbacks. This call is always on the same binder thread, so we can just synchronize
+ // on the copying of the listener list.
synchronized (mTaskStackListeners) {
- mTmpListeners.clear();
mTmpListeners.addAll(mTaskStackListeners);
}
for (int i = mTmpListeners.size() - 1; i >= 0; i--) {
mTmpListeners.get(i).onTaskStackChangedBackground();
}
+ mTmpListeners.clear();
mHandler.removeMessages(H.ON_TASK_STACK_CHANGED);
mHandler.sendEmptyMessage(H.ON_TASK_STACK_CHANGED);
@@ -230,6 +239,11 @@
.sendToTarget();
}
+ @Override
+ public void onTaskDescriptionChanged(RunningTaskInfo taskInfo) {
+ mHandler.obtainMessage(H.ON_TASK_DESCRIPTION_CHANGED, taskInfo).sendToTarget();
+ }
+
private final class H extends Handler {
private static final int ON_TASK_STACK_CHANGED = 1;
private static final int ON_TASK_SNAPSHOT_CHANGED = 2;
@@ -254,6 +268,7 @@
private static final int ON_TASK_LIST_UPDATED = 21;
private static final int ON_SINGLE_TASK_DISPLAY_EMPTY = 22;
private static final int ON_TASK_LIST_FROZEN_UNFROZEN = 23;
+ private static final int ON_TASK_DESCRIPTION_CHANGED = 24;
public H(Looper looper) {
@@ -421,6 +436,13 @@
}
break;
}
+ case ON_TASK_DESCRIPTION_CHANGED: {
+ final RunningTaskInfo info = (RunningTaskInfo) msg.obj;
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onTaskDescriptionChanged(info);
+ }
+ break;
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 46b4c6b..21b52c1 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -169,12 +169,15 @@
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
mSeparator = separator;
mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
- mSimSlotsNumber = ((TelephonyManager) context.getSystemService(
- Context.TELEPHONY_SERVICE)).getSupportedModemCount();
+ mSimSlotsNumber = getTelephonyManager().getSupportedModemCount();
mSimErrorState = new boolean[mSimSlotsNumber];
mMainHandler = Dependency.get(Dependency.MAIN_HANDLER);
}
+ private TelephonyManager getTelephonyManager() {
+ return (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ }
+
/**
* Checks if there are faulty cards. Adds the text depending on the slot of the card
*
@@ -190,7 +193,7 @@
CharSequence carrierTextForSimIOError = getCarrierTextForSimState(
IccCardConstants.State.CARD_IO_ERROR, carrier);
// mSimErrorState has the state of each sim indexed by slotID.
- for (int index = 0; index < mSimErrorState.length; index++) {
+ for (int index = 0; index < getTelephonyManager().getActiveModemCount(); index++) {
if (!mSimErrorState[index]) {
continue;
}
@@ -223,8 +226,7 @@
* @param callback Callback to provide text updates
*/
public void setListening(CarrierTextCallback callback) {
- TelephonyManager telephonyManager = ((TelephonyManager) mContext
- .getSystemService(Context.TELEPHONY_SERVICE));
+ TelephonyManager telephonyManager = getTelephonyManager();
if (callback != null) {
mCarrierTextCallback = callback;
// TODO(b/140034799)
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
index 1c30762..ecd8c8d 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButton.java
@@ -50,14 +50,6 @@
* allows the user to return to the call.
*/
public class EmergencyButton extends Button {
- private static final Intent INTENT_EMERGENCY_DIAL = new Intent()
- .setAction(EmergencyDialerConstants.ACTION_DIAL)
- .setPackage("com.android.phone")
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- | Intent.FLAG_ACTIVITY_CLEAR_TOP)
- .putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
- EmergencyDialerConstants.ENTRY_TYPE_LOCKSCREEN_BUTTON);
private static final String LOG_TAG = "EmergencyButton";
private final EmergencyAffordanceManager mEmergencyAffordanceManager;
@@ -189,7 +181,15 @@
} else {
Dependency.get(KeyguardUpdateMonitor.class).reportEmergencyCallAction(
true /* bypassHandler */);
- getContext().startActivityAsUser(INTENT_EMERGENCY_DIAL,
+ Intent emergencyDialIntent =
+ getTelecommManager().createLaunchEmergencyDialerIntent(null /* number*/)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP)
+ .putExtra(EmergencyDialerConstants.EXTRA_ENTRY_TYPE,
+ EmergencyDialerConstants.ENTRY_TYPE_LOCKSCREEN_BUTTON);
+
+ getContext().startActivityAsUser(emergencyDialIntent,
ActivityOptions.makeCustomAnimation(getContext(), 0, 0).toBundle(),
new UserHandle(KeyguardUpdateMonitor.getCurrentUser()));
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
index 1395fd9..64b4d32 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -75,7 +75,6 @@
return SecurityMode.SimPin;
}
- // TODO(b/140034863)
final int security = whitelistIpcs(() ->
mLockPatternUtils.getActivePasswordQuality(userId));
switch (security) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index 9c0a71c..b1502b9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -104,7 +104,12 @@
private void setLockedSimMessage() {
boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
- int count = TelephonyManager.getDefault().getSimCount();
+ int count = 1;
+ TelephonyManager telephonyManager =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ if (telephonyManager != null) {
+ count = telephonyManager.getActiveModemCount();
+ }
Resources rez = getResources();
String msg;
TypedArray array = mContext.obtainStyledAttributes(new int[] { R.attr.wallpaperTextColor });
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index fc888e1..70237a0 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -164,7 +164,12 @@
}
boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mContext, mSubId);
- int count = TelephonyManager.getDefault().getSimCount();
+ int count = 1;
+ TelephonyManager telephonyManager =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ if (telephonyManager != null) {
+ count = telephonyManager.getActiveModemCount();
+ }
Resources rez = getResources();
String msg;
TypedArray array = mContext.obtainStyledAttributes(new int[] { R.attr.wallpaperTextColor });
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 27410be..0b0922a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -99,7 +99,10 @@
import com.android.internal.widget.LockPatternUtils;
import com.android.settingslib.WirelessUtils;
import com.android.systemui.DejankUtils;
+import com.android.systemui.DumpController;
+import com.android.systemui.Dumpable;
import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.MainLooper;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
@@ -126,7 +129,7 @@
* to be updated.
*/
@Singleton
-public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
+public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpable {
private static final String TAG = "KeyguardUpdateMonitor";
private static final boolean DEBUG = KeyguardConstants.DEBUG;
@@ -1499,11 +1502,14 @@
@VisibleForTesting
@Inject
- protected KeyguardUpdateMonitor(Context context, @MainLooper Looper mainLooper) {
+ protected KeyguardUpdateMonitor(Context context, @MainLooper Looper mainLooper,
+ BroadcastDispatcher broadcastDispatcher,
+ DumpController dumpController) {
mContext = context;
mSubscriptionManager = SubscriptionManager.from(context);
mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
mStrongAuthTracker = new StrongAuthTracker(context, this::notifyStrongAuthStateChanged);
+ dumpController.registerDumpable(this);
mHandler = new Handler(mainLooper) {
@Override
@@ -1641,12 +1647,12 @@
filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
- context.registerReceiver(mBroadcastReceiver, filter, null, mHandler);
+ broadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, mHandler);
final IntentFilter bootCompleteFilter = new IntentFilter();
bootCompleteFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
bootCompleteFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
- context.registerReceiver(mBroadcastReceiver, bootCompleteFilter, null, mHandler);
+ broadcastDispatcher.registerReceiver(mBroadcastReceiver, bootCompleteFilter, mHandler);
final IntentFilter allUserFilter = new IntentFilter();
allUserFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
@@ -1657,8 +1663,8 @@
allUserFilter.addAction(ACTION_USER_UNLOCKED);
allUserFilter.addAction(ACTION_USER_STOPPED);
allUserFilter.addAction(ACTION_USER_REMOVED);
- context.registerReceiverAsUser(mBroadcastAllReceiver, UserHandle.ALL, allUserFilter,
- null, mHandler);
+ broadcastDispatcher.registerReceiver(mBroadcastAllReceiver, allUserFilter, mHandler,
+ UserHandle.ALL);
mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionListener);
try {
@@ -2643,8 +2649,10 @@
// that don't return the complete set of values and have different types. In Keyguard we
// need IccCardConstants, but TelephonyManager would only give us
// TelephonyManager.SIM_STATE*, so we retrieve it manually.
- final TelephonyManager tele = TelephonyManager.from(mContext);
- int simState = tele.getSimState(slotId);
+ final TelephonyManager tele =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ int simState = (tele != null) ?
+ tele.getSimState(slotId) : TelephonyManager.SIM_STATE_UNKNOWN;
State state;
try {
state = State.intToState(simState);
@@ -2787,6 +2795,7 @@
}
}
+ @Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("KeyguardUpdateMonitor state:");
pw.println(" SIM States:");
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index 9e2464e..dfabe69 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -32,6 +32,7 @@
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Observer;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManager.DockEventListener;
@@ -125,9 +126,9 @@
@Inject
public ClockManager(Context context, InjectionInflationController injectionInflater,
PluginManager pluginManager, SysuiColorExtractor colorExtractor,
- @Nullable DockManager dockManager) {
+ @Nullable DockManager dockManager, BroadcastDispatcher broadcastDispatcher) {
this(context, injectionInflater, pluginManager, colorExtractor,
- context.getContentResolver(), new CurrentUserObservable(context),
+ context.getContentResolver(), new CurrentUserObservable(broadcastDispatcher),
new SettingsWrapper(context.getContentResolver()), dockManager);
}
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index ce61a00..2afcb12 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -51,9 +51,11 @@
import com.android.settingslib.Utils;
import com.android.settingslib.graph.ThemedBatteryDrawable;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
@@ -111,16 +113,13 @@
private int mNonAdaptedForegroundColor;
private int mNonAdaptedBackgroundColor;
- public BatteryMeterView(Context context) {
- this(context, null, 0);
- }
-
public BatteryMeterView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BatteryMeterView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ BroadcastDispatcher broadcastDispatcher = Dependency.get(BroadcastDispatcher.class);
setOrientation(LinearLayout.HORIZONTAL);
setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
@@ -139,7 +138,8 @@
addOnAttachStateChangeListener(
- new DisableStateTracker(DISABLE_NONE, DISABLE2_SYSTEM_ICONS));
+ new DisableStateTracker(DISABLE_NONE, DISABLE2_SYSTEM_ICONS,
+ Dependency.get(CommandQueue.class)));
setupLayoutTransition();
@@ -159,7 +159,7 @@
// Init to not dark at all.
onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
- mUserTracker = new CurrentUserTracker(mContext) {
+ mUserTracker = new CurrentUserTracker(broadcastDispatcher) {
@Override
public void onUserSwitched(int newUserId) {
mUser = newUserId;
diff --git a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
index a94952c..8e472f9 100644
--- a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
+++ b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
@@ -47,6 +47,7 @@
private int mLightColor;
private int mDarkColor;
private Path mPath;
+ private boolean mRequiresInvalidate;
public CornerHandleView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -67,6 +68,15 @@
updatePath();
}
+ @Override
+ public void setAlpha(float alpha) {
+ super.setAlpha(alpha);
+ if (alpha > 0f && mRequiresInvalidate) {
+ mRequiresInvalidate = false;
+ invalidate();
+ }
+ }
+
private void updatePath() {
mPath = new Path();
@@ -104,11 +114,16 @@
* appropriately. Intention is to match the home handle color.
*/
public void updateDarkness(float darkIntensity) {
- mPaint.setColor((int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
- mLightColor,
- mDarkColor));
- if (getVisibility() == VISIBLE) {
- invalidate();
+ int color = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
+ mLightColor, mDarkColor);
+ if (mPaint.getColor() != color) {
+ mPaint.setColor(color);
+ if (getVisibility() == VISIBLE && getAlpha() > 0) {
+ invalidate();
+ } else {
+ // If we are currently invisible, then invalidate when we are next made visible
+ mRequiresInvalidate = true;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 486d02c..b3f32af 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -63,6 +63,7 @@
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
import com.android.systemui.shared.system.PackageManagerWrapper;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
@@ -326,6 +327,7 @@
@Inject Lazy<KeyguardSecurityModel> mKeyguardSecurityModel;
@Inject Lazy<DozeParameters> mDozeParameters;
@Inject Lazy<IWallpaperManager> mWallpaperManager;
+ @Inject Lazy<CommandQueue> mCommandQueue;
@Inject
public Dependency() {
@@ -514,6 +516,7 @@
mProviders.put(KeyguardSecurityModel.class, mKeyguardSecurityModel::get);
mProviders.put(DozeParameters.class, mDozeParameters::get);
mProviders.put(IWallpaperManager.class, mWallpaperManager::get);
+ mProviders.put(CommandQueue.class, mCommandQueue::get);
// TODO(b/118592525): to support multi-display , we start to add something which is
// per-display, while others may be global. I think it's time to add
diff --git a/packages/SystemUI/src/com/android/systemui/DumpController.kt b/packages/SystemUI/src/com/android/systemui/DumpController.kt
index 65f1abd..8c7075b 100644
--- a/packages/SystemUI/src/com/android/systemui/DumpController.kt
+++ b/packages/SystemUI/src/com/android/systemui/DumpController.kt
@@ -47,6 +47,16 @@
/**
* Adds a [Dumpable] dumpable to be dumped.
*
+ * @param dumpable the [Dumpable] to be added
+ */
+ fun registerDumpable(dumpable: Dumpable) {
+ Preconditions.checkNotNull(dumpable, "The dumpable to be added cannot be null")
+ registerDumpable(dumpable.javaClass.simpleName, dumpable)
+ }
+
+ /**
+ * Adds a [Dumpable] dumpable to be dumped.
+ *
* @param tag a string tag to associate with this dumpable. Tags must be globally unique; this
* method will throw if the same tag has already been registered. Tags can be used to
* filter output when debugging.
@@ -79,11 +89,11 @@
/**
* Dump all the [Dumpable] registered with the controller
*/
- override fun dump(fd: FileDescriptor?, pw: PrintWriter, args: Array<String>?) {
+ override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) {
pw.println("DumpController state:")
- val filter = if (args != null && args.size >= 3 &&
- args[0] == "dependency" && args[1] == "DumpController") {
+ val filter = if (args.size >= 3 && args[0].toLowerCase() == "dependency" &&
+ args[1] == "DumpController") {
ArraySet(args[2].split(',').map { it.toLowerCase() })
} else {
null
diff --git a/packages/SystemUI/src/com/android/systemui/Dumpable.java b/packages/SystemUI/src/com/android/systemui/Dumpable.java
index 65a6844..10a0643 100644
--- a/packages/SystemUI/src/com/android/systemui/Dumpable.java
+++ b/packages/SystemUI/src/com/android/systemui/Dumpable.java
@@ -14,9 +14,24 @@
package com.android.systemui;
+import androidx.annotation.NonNull;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
+/**
+ * Implemented by classes who want to be in:
+ * {@code adb shell dumpsys activity service com.android.systemui}
+ *
+ * @see DumpController
+ */
public interface Dumpable {
- void dump(FileDescriptor fd, PrintWriter pw, String[] args);
+
+ /**
+ * Called when it's time to dump the internal state
+ * @param fd A file descriptor.
+ * @param pw Where to write your dump to.
+ * @param args Arguments.
+ */
+ void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args);
}
diff --git a/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java b/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java
index 3a8536b..4afa969 100644
--- a/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/GuestResumeSessionReceiver.java
@@ -32,6 +32,7 @@
import android.util.Log;
import android.view.WindowManagerGlobal;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.statusbar.phone.SystemUIDialog;
/**
@@ -45,10 +46,14 @@
private Dialog mNewSessionDialog;
- public void register(Context context) {
+ /**
+ * Register this receiver with the {@link BroadcastDispatcher}
+ *
+ * @param broadcastDispatcher to register the receiver.
+ */
+ public void register(BroadcastDispatcher broadcastDispatcher) {
IntentFilter f = new IntentFilter(Intent.ACTION_USER_SWITCHED);
- context.registerReceiverAsUser(this, UserHandle.SYSTEM,
- f, null /* permission */, null /* scheduler */);
+ broadcastDispatcher.registerReceiver(this, f, null /* handler */, UserHandle.SYSTEM);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/LatencyTester.java b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
index 30a60ab..1a47dac 100644
--- a/packages/SystemUI/src/com/android/systemui/LatencyTester.java
+++ b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
@@ -29,6 +29,7 @@
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import javax.inject.Inject;
@@ -49,13 +50,16 @@
"com.android.systemui.latency.ACTION_TURN_ON_SCREEN";
private final BiometricUnlockController mBiometricUnlockController;
private final PowerManager mPowerManager;
+ private final BroadcastDispatcher mBroadcastDispatcher;
@Inject
public LatencyTester(Context context, BiometricUnlockController biometricUnlockController,
- PowerManager powerManager) {
+ PowerManager powerManager, BroadcastDispatcher broadcastDispatcher) {
super(context);
+
mBiometricUnlockController = biometricUnlockController;
mPowerManager = powerManager;
+ mBroadcastDispatcher = broadcastDispatcher;
}
@Override
@@ -67,7 +71,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_FINGERPRINT_WAKE);
filter.addAction(ACTION_TURN_ON_SCREEN);
- mContext.registerReceiver(new BroadcastReceiver() {
+ mBroadcastDispatcher.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 8a99e451..ab7eec5 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -67,6 +67,8 @@
import com.android.internal.util.Preconditions;
import com.android.systemui.RegionInterceptingFrameLayout.RegionInterceptableView;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.plugins.qs.QS;
@@ -103,6 +105,9 @@
private final Lazy<StatusBar> mStatusBarLazy;
private DisplayManager mDisplayManager;
+ private final BroadcastDispatcher mBroadcastDispatcher;
+ private final Handler mMainHandler;
+ private final TunerService mTunerService;
private DisplayManager.DisplayListener mDisplayListener;
@VisibleForTesting
@@ -140,9 +145,16 @@
}
@Inject
- public ScreenDecorations(Context context, Lazy<StatusBar> statusBarLazy) {
+ public ScreenDecorations(Context context,
+ Lazy<StatusBar> statusBarLazy,
+ @MainHandler Handler handler,
+ BroadcastDispatcher broadcastDispatcher,
+ TunerService tunerService) {
super(context);
mStatusBarLazy = statusBarLazy;
+ mMainHandler = handler;
+ mBroadcastDispatcher = broadcastDispatcher;
+ mTunerService = tunerService;
}
@Override
@@ -239,8 +251,7 @@
mWindowManager.getDefaultDisplay().getMetrics(metrics);
mDensity = metrics.density;
- Dependency.get(Dependency.MAIN_HANDLER).post(
- () -> Dependency.get(TunerService.class).addTunable(this, SIZE));
+ mMainHandler.post(() -> mTunerService.addTunable(this, SIZE));
// Watch color inversion and invert the overlay as needed.
mColorInversionSetting = new SecureSetting(mContext, mHandler,
@@ -255,7 +266,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);
- mContext.registerReceiver(mIntentReceiver, filter, null /* permission */, mHandler);
+ mBroadcastDispatcher.registerReceiver(mIntentReceiver, filter, mHandler);
mOverlay.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java b/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java
index 10009f5..72a4030 100644
--- a/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/SizeCompatModeActivityController.java
@@ -47,7 +47,11 @@
import java.lang.ref.WeakReference;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/** Shows a restart-activity button when the foreground activity is in size compatibility mode. */
+@Singleton
public class SizeCompatModeActivityController extends SystemUI implements CommandQueue.Callbacks {
private static final String TAG = "SizeCompatMode";
@@ -55,17 +59,17 @@
private final SparseArray<RestartActivityButton> mActiveButtons = new SparseArray<>(1);
/** Avoid creating display context frequently for non-default display. */
private final SparseArray<WeakReference<Context>> mDisplayContextCache = new SparseArray<>(0);
+ private final CommandQueue mCommandQueue;
/** Only show once automatically in the process life. */
private boolean mHasShownHint;
- public SizeCompatModeActivityController(Context context) {
- this(context, ActivityManagerWrapper.getInstance());
- }
-
@VisibleForTesting
- SizeCompatModeActivityController(Context context, ActivityManagerWrapper am) {
+ @Inject
+ SizeCompatModeActivityController(Context context, ActivityManagerWrapper am,
+ CommandQueue commandQueue) {
super(context);
+ mCommandQueue = commandQueue;
am.registerTaskStackListener(new TaskStackChangeListener() {
@Override
public void onSizeCompatModeActivityChanged(int displayId, IBinder activityToken) {
@@ -77,7 +81,7 @@
@Override
public void start() {
- SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this);
+ mCommandQueue.addCallback(this);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java b/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java
index 92fbd25..7a4ef2b 100644
--- a/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/SliceBroadcastRelayHandler.java
@@ -28,19 +28,27 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.SliceBroadcastRelay;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
/**
* Allows settings to register certain broadcasts to launch the settings app for pinned slices.
* @see SliceBroadcastRelay
*/
+@Singleton
public class SliceBroadcastRelayHandler extends SystemUI {
private static final String TAG = "SliceBroadcastRelay";
private static final boolean DEBUG = false;
private final ArrayMap<Uri, BroadcastRelay> mRelays = new ArrayMap<>();
+ private final BroadcastDispatcher mBroadcastDispatcher;
- public SliceBroadcastRelayHandler(Context context) {
+ @Inject
+ public SliceBroadcastRelayHandler(Context context, BroadcastDispatcher broadcastDispatcher) {
super(context);
+ mBroadcastDispatcher = broadcastDispatcher;
}
@Override
@@ -48,9 +56,10 @@
if (DEBUG) Log.d(TAG, "Start");
IntentFilter filter = new IntentFilter(SliceBroadcastRelay.ACTION_REGISTER);
filter.addAction(SliceBroadcastRelay.ACTION_UNREGISTER);
- mContext.registerReceiver(mReceiver, filter);
+ mBroadcastDispatcher.registerReceiver(mReceiver, filter);
}
+ // This does not use BroadcastDispatcher as the filter may have schemas or mime types.
@VisibleForTesting
void handleIntent(Intent intent) {
if (SliceBroadcastRelay.ACTION_REGISTER.equals(intent.getAction())) {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
index 746515a..cacbf96 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java
@@ -19,6 +19,7 @@
import android.app.Activity;
import android.app.Application;
import android.app.Service;
+import android.content.BroadcastReceiver;
import android.content.ContentProvider;
import android.content.Context;
import android.content.Intent;
@@ -125,6 +126,25 @@
return super.instantiateServiceCompat(cl, className, intent);
}
+ @NonNull
+ @Override
+ public BroadcastReceiver instantiateReceiverCompat(@NonNull ClassLoader cl,
+ @NonNull String className, @Nullable Intent intent)
+ throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+ if (mComponentHelper == null) {
+ // This shouldn't happen, but does when a device is freshly formatted.
+ // Bug filed against framework to take a look: http://b/141008541
+ SystemUIFactory.getInstance().getRootComponent().inject(
+ SystemUIAppComponentFactory.this);
+ }
+ BroadcastReceiver receiver = mComponentHelper.resolveBroadcastReceiver(className);
+ if (receiver != null) {
+ return receiver;
+ }
+
+ return super.instantiateReceiverCompat(cl, className, intent);
+ }
+
/**
* A callback that receives a Context when one is ready.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 022bf06..aab4041 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -24,23 +24,14 @@
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
-import android.os.Handler;
-import android.os.Looper;
import android.os.Process;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
-import android.util.ArraySet;
import android.util.Log;
import android.util.TimingsTraceLog;
import com.android.systemui.dagger.ContextComponentHelper;
-import com.android.systemui.plugins.OverlayPlugin;
-import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.StatusBarWindowController;
import com.android.systemui.util.NotificationChannels;
import java.lang.reflect.Constructor;
@@ -224,65 +215,6 @@
}
Dependency.get(InitController.class).executePostInitTasks();
log.traceEnd();
- final Handler mainHandler = new Handler(Looper.getMainLooper());
- Dependency.get(PluginManager.class).addPluginListener(
- new PluginListener<OverlayPlugin>() {
- private ArraySet<OverlayPlugin> mOverlays = new ArraySet<>();
-
- @Override
- public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
- mainHandler.post(new Runnable() {
- @Override
- public void run() {
- StatusBar statusBar = getComponent(StatusBar.class);
- if (statusBar != null) {
- plugin.setup(statusBar.getStatusBarWindow(),
- statusBar.getNavigationBarView(), new Callback(plugin),
- Dependency.get(DozeParameters.class));
- }
- }
- });
- }
-
- @Override
- public void onPluginDisconnected(OverlayPlugin plugin) {
- mainHandler.post(new Runnable() {
- @Override
- public void run() {
- mOverlays.remove(plugin);
- Dependency.get(StatusBarWindowController.class).setForcePluginOpen(
- mOverlays.size() != 0);
- }
- });
- }
-
- class Callback implements OverlayPlugin.Callback {
- private final OverlayPlugin mPlugin;
-
- Callback(OverlayPlugin plugin) {
- mPlugin = plugin;
- }
-
- @Override
- public void onHoldStatusBarOpenChange() {
- if (mPlugin.holdStatusBarOpen()) {
- mOverlays.add(mPlugin);
- } else {
- mOverlays.remove(mPlugin);
- }
- mainHandler.post(new Runnable() {
- @Override
- public void run() {
- Dependency.get(StatusBarWindowController.class)
- .setStateListener(b -> mOverlays.forEach(
- o -> o.setCollapseDesired(b)));
- Dependency.get(StatusBarWindowController.class)
- .setForcePluginOpen(mOverlays.size() != 0);
- }
- });
- }
- }
- }, OverlayPlugin.class, true /* Allow multiple plugins */);
mServicesStarted = true;
}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 0a547b6..b524597 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -33,6 +33,7 @@
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
@@ -124,6 +125,15 @@
return new StatusBarKeyguardViewManager(context, viewMediatorCallback, lockPatternUtils);
}
+ /**
+ * Creates an instance of ScreenshotNotificationSmartActionsProvider.
+ * This method is overridden in vendor specific implementation of Sys UI.
+ */
+ public ScreenshotNotificationSmartActionsProvider
+ createScreenshotNotificationSmartActionsProvider() {
+ return new ScreenshotNotificationSmartActionsProvider();
+ }
+
public KeyguardBouncer createKeyguardBouncer(Context context, ViewMediatorCallback callback,
LockPatternUtils lockPatternUtils, ViewGroup container,
DismissCallbackRegistry dismissCallbackRegistry,
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 3f56ff0..8825f12 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -67,13 +67,11 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (args != null && args.length > 0 && args[0].equals("--config")) {
- dumpConfig(pw);
- return;
- }
-
dumpServices(((SystemUIApplication) getApplication()).getServices(), fd, pw, args);
- dumpConfig(pw);
+
+ if (args == null || args.length == 0 || args[0].equals("--config")) {
+ dumpConfig(pw);
+ }
}
static void dumpServices(
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
index 3ff1b97..46ae84a 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
@@ -34,6 +34,7 @@
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -161,6 +162,7 @@
private final Lazy<SysUiState> mSysUiFlagContainer;
private final Lazy<WakefulnessLifecycle> mWakefulnessLifecycle;
private final Lazy<PackageManagerWrapper> mPackageManagerWrapper;
+ private final Lazy<BroadcastDispatcher> mBroadcastDispatcher;
private boolean mOnLockscreen;
private boolean mIsDozing;
@@ -193,7 +195,8 @@
Lazy<OverviewProxyService> overviewProxyService,
Lazy<SysUiState> sysUiFlagContainer,
Lazy<WakefulnessLifecycle> wakefulnessLifecycle,
- Lazy<PackageManagerWrapper> packageManagerWrapper) {
+ Lazy<PackageManagerWrapper> packageManagerWrapper,
+ Lazy<BroadcastDispatcher> broadcastDispatcher) {
mClock = clock;
mHandler = handler;
mPhenotypeHelper = phenotypeHelper;
@@ -207,6 +210,7 @@
for (String action : DEFAULT_HOME_CHANGE_ACTIONS) {
mDefaultHomeIntentFilter.addAction(action);
}
+ mBroadcastDispatcher = broadcastDispatcher;
}
@Override
@@ -215,7 +219,8 @@
mAssistHandleCallbacks = callbacks;
mConsecutiveTaskSwitches = 0;
mDefaultHome = getCurrentDefaultHome();
- context.registerReceiver(mDefaultHomeBroadcastReceiver, mDefaultHomeIntentFilter);
+ mBroadcastDispatcher.get()
+ .registerReceiver(mDefaultHomeBroadcastReceiver, mDefaultHomeIntentFilter);
mOnLockscreen = onLockscreen(mStatusBarStateController.get().getState());
mIsDozing = mStatusBarStateController.get().isDozing();
mStatusBarStateController.get().addCallback(mStatusBarStateListener);
@@ -244,7 +249,7 @@
public void onModeDeactivated() {
mAssistHandleCallbacks = null;
if (mContext != null) {
- mContext.unregisterReceiver(mDefaultHomeBroadcastReceiver);
+ mBroadcastDispatcher.get().unregisterReceiver(mDefaultHomeBroadcastReceiver);
Settings.Secure.putLong(mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, 0);
Settings.Secure.putInt(mContext.getContentResolver(), LEARNING_EVENT_COUNT_KEY, 0);
Settings.Secure.putLong(mContext.getContentResolver(), LEARNED_HINT_LAST_SHOWN_KEY, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 1f950f6..398826c 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -44,8 +44,8 @@
import com.android.systemui.ConfigurationChangedReceiver;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.assist.ui.DefaultUiController;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -130,6 +130,7 @@
private AssistOrbContainer mView;
private final DeviceProvisionedController mDeviceProvisionedController;
+ private final CommandQueue mCommandQueue;
protected final AssistUtils mAssistUtils;
private final boolean mShouldEnableOrb;
@@ -160,13 +161,16 @@
DeviceProvisionedController controller,
Context context,
AssistUtils assistUtils,
- AssistHandleBehaviorController handleController) {
+ AssistHandleBehaviorController handleController,
+ CommandQueue commandQueue,
+ BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mDeviceProvisionedController = controller;
+ mCommandQueue = commandQueue;
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mAssistUtils = assistUtils;
mAssistDisclosure = new AssistDisclosure(context, new Handler());
- mPhoneStateMonitor = new PhoneStateMonitor(context);
+ mPhoneStateMonitor = new PhoneStateMonitor(context, broadcastDispatcher);
mHandleController = handleController;
registerVoiceInteractionSessionListener();
@@ -339,7 +343,7 @@
}
// Close Recent Apps if needed
- SysUiServiceProvider.getComponent(mContext, CommandQueue.class).animateCollapsePanels(
+ mCommandQueue.animateCollapsePanels(
CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL | CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
false /* force */);
diff --git a/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java b/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java
index e73dc4a..95d611a 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/PhoneStateMonitor.java
@@ -29,6 +29,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.PackageManagerWrapper;
@@ -67,7 +68,7 @@
private boolean mLauncherShowing;
@Nullable private ComponentName mDefaultHome;
- PhoneStateMonitor(Context context) {
+ PhoneStateMonitor(Context context, BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mStatusBarStateController = Dependency.get(StatusBarStateController.class);
@@ -77,7 +78,7 @@
for (String action : DEFAULT_HOME_CHANGE_ACTIONS) {
intentFilter.addAction(action);
}
- mContext.registerReceiver(new BroadcastReceiver() {
+ broadcastDispatcher.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
mDefaultHome = getCurrentDefaultHome();
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java b/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java
index baa3a4a..c641943 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java
@@ -67,8 +67,10 @@
}
/** Sets the edge light color. */
- public void setColor(@ColorInt int color) {
+ public boolean setColor(@ColorInt int color) {
+ boolean changed = mColor != color;
mColor = color;
+ return changed;
}
/** Returns the edge light length, in units of the total device perimeter. */
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
index 570b911..e5121a8 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
@@ -259,10 +259,13 @@
if (mUseNavBarColor) {
@ColorInt int invocationColor = (int) ArgbEvaluator.getInstance().evaluate(
darkIntensity, mLightColor, mDarkColor);
+ boolean changed = true;
for (EdgeLight light : mAssistInvocationLights) {
- light.setColor(invocationColor);
+ changed &= light.setColor(invocationColor);
}
- invalidate();
+ if (changed) {
+ invalidate();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
index f5f1fad..84a592d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java
@@ -298,7 +298,10 @@
.getDimension(R.dimen.biometric_dialog_icon_padding);
mIconView.setY(getHeight() - mIconView.getHeight() - iconPadding);
- final int newHeight = mIconView.getHeight() + 2 * (int) iconPadding;
+ // Subtract the vertical padding from the new height since it's only used to create
+ // extra space between the other elements, and not part of the actual icon.
+ final int newHeight = mIconView.getHeight() + 2 * (int) iconPadding
+ - mIconView.getPaddingTop() - mIconView.getPaddingBottom();
mPanelController.updateForContentDimensions(mMediumWidth, newHeight,
0 /* animateDurationMs */);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 446ed25..6b0d3c8 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -23,7 +23,10 @@
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
import android.app.TaskStackListener;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.hardware.biometrics.Authenticator;
@@ -47,16 +50,21 @@
import java.util.List;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Receives messages sent from {@link com.android.server.biometrics.BiometricService} and shows the
* appropriate biometric UI (e.g. BiometricDialogView).
*/
+@Singleton
public class AuthController extends SystemUI implements CommandQueue.Callbacks,
AuthDialogCallback {
private static final String TAG = "BiometricPrompt/AuthController";
private static final boolean DEBUG = true;
+ private final CommandQueue mCommandQueue;
private final Injector mInjector;
// TODO: These should just be saved from onSaveState
@@ -80,6 +88,28 @@
}
}
+ @VisibleForTesting
+ final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mCurrentDialog != null
+ && Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
+ Log.w(TAG, "ACTION_CLOSE_SYSTEM_DIALOGS received");
+ mCurrentDialog.dismissWithoutCallback(true /* animate */);
+ mCurrentDialog = null;
+
+ try {
+ if (mReceiver != null) {
+ mReceiver.onDialogDismissed(BiometricPrompt.DISMISSED_REASON_USER_CANCEL);
+ mReceiver = null;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Remote exception", e);
+ }
+ }
+ }
+ };
+
private final Runnable mTaskStackChangedRunnable = () -> {
if (mCurrentDialog != null) {
try {
@@ -189,14 +219,21 @@
}
}
- public AuthController(Context context) {
- this(context, new Injector());
+ @Inject
+ public AuthController(Context context, CommandQueue commandQueue) {
+ this(context, commandQueue, new Injector());
}
@VisibleForTesting
- AuthController(Context context, Injector injector) {
+ AuthController(Context context, CommandQueue commandQueue, Injector injector) {
super(context);
+ mCommandQueue = commandQueue;
mInjector = injector;
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+
+ context.registerReceiver(mBroadcastReceiver, filter);
}
@Override
@@ -205,7 +242,7 @@
if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
|| pm.hasSystemFeature(PackageManager.FEATURE_FACE)
|| pm.hasSystemFeature(PackageManager.FEATURE_IRIS)) {
- getComponent(CommandQueue.class).addCallback(this);
+ mCommandQueue.addCallback(this);
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mActivityTaskManager = mInjector.getActivityTaskManager();
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
index ff4711c..776189b7 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
@@ -23,6 +23,7 @@
import android.os.Looper
import android.os.Message
import android.os.UserHandle
+import android.text.TextUtils
import android.util.Log
import android.util.SparseArray
import com.android.internal.annotations.VisibleForTesting
@@ -55,7 +56,8 @@
* a given broadcast.
*
* Use only for IntentFilters with actions and optionally categories. It does not support,
- * permissions, schemes or data types. Cannot be used for getting sticky broadcasts.
+ * permissions, schemes, data types or data authorities.
+ * Cannot be used for getting sticky broadcasts.
*/
@Singleton
open class BroadcastDispatcher @Inject constructor (
@@ -72,11 +74,14 @@
*
* @param receiver A receiver to dispatch the [Intent]
* @param filter A filter to determine what broadcasts should be dispatched to this receiver.
- * It will only take into account actions and categories for filtering.
+ * It will only take into account actions and categories for filtering. It must
+ * have at least one action.
* @param handler A handler to dispatch [BroadcastReceiver.onReceive]. By default, it is the
* main handler. Pass `null` to use the default.
* @param user A user handle to determine which broadcast should be dispatched to this receiver.
* By default, it is the current user.
+ * @throws IllegalArgumentException if the filter has other constraints that are not actions or
+ * categories or the filter has no actions.
*/
@JvmOverloads
fun registerReceiver(
@@ -85,12 +90,23 @@
handler: Handler? = mainHandler,
user: UserHandle = context.user
) {
+ checkFilter(filter)
this.handler
.obtainMessage(MSG_ADD_RECEIVER,
ReceiverData(receiver, filter, handler ?: mainHandler, user))
.sendToTarget()
}
+ private fun checkFilter(filter: IntentFilter) {
+ val sb = StringBuilder()
+ if (filter.countActions() == 0) sb.append("Filter must contain at least one action. ")
+ if (filter.countDataAuthorities() != 0) sb.append("Filter cannot contain DataAuthorities. ")
+ if (filter.countDataPaths() != 0) sb.append("Filter cannot contain DataPaths. ")
+ if (filter.countDataSchemes() != 0) sb.append("Filter cannot contain DataSchemes. ")
+ if (filter.countDataTypes() != 0) sb.append("Filter cannot contain DataTypes. ")
+ if (!TextUtils.isEmpty(sb)) throw IllegalArgumentException(sb.toString())
+ }
+
/**
* Unregister receiver for all users.
* <br>
@@ -117,10 +133,10 @@
protected open fun createUBRForUser(userId: Int) =
UserBroadcastDispatcher(context, userId, mainHandler, bgLooper)
- override fun dump(fd: FileDescriptor?, pw: PrintWriter?, args: Array<out String>?) {
- pw?.println("Broadcast dispatcher:")
+ override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
+ pw.println("Broadcast dispatcher:")
for (index in 0 until receiversByUser.size()) {
- pw?.println(" User ${receiversByUser.keyAt(index)}")
+ pw.println(" User ${receiversByUser.keyAt(index)}")
receiversByUser.valueAt(index).dump(fd, pw, args)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
index 54f9950..24357a7 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
@@ -31,6 +31,7 @@
import java.io.FileDescriptor
import java.io.PrintWriter
import java.util.concurrent.atomic.AtomicBoolean
+import java.util.concurrent.atomic.AtomicInteger
private const val MSG_REGISTER_RECEIVER = 0
private const val MSG_UNREGISTER_RECEIVER = 1
@@ -50,6 +51,13 @@
private val bgLooper: Looper
) : BroadcastReceiver(), Dumpable {
+ companion object {
+ // Used only for debugging. If not debugging, this variable will not be accessed and all
+ // received broadcasts will be tagged with 0. However, as DEBUG is false, nothing will be
+ // logged
+ val index = AtomicInteger(0)
+ }
+
private val bgHandler = object : Handler(bgLooper) {
override fun handleMessage(msg: Message) {
when (msg.what) {
@@ -97,7 +105,10 @@
private val receiverToReceiverData = ArrayMap<BroadcastReceiver, MutableSet<ReceiverData>>()
override fun onReceive(context: Context, intent: Intent) {
- bgHandler.post(HandleBroadcastRunnable(actionsToReceivers, context, intent, pendingResult))
+ val id = if (DEBUG) index.getAndIncrement() else 0
+ if (DEBUG) Log.w(TAG, "[$id] Received $intent")
+ bgHandler.post(
+ HandleBroadcastRunnable(actionsToReceivers, context, intent, pendingResult, id))
}
/**
@@ -149,11 +160,11 @@
}
}
- override fun dump(fd: FileDescriptor?, pw: PrintWriter?, args: Array<out String>?) {
- pw?.println(" Registered=${registered.get()}")
+ override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
+ pw.println(" Registered=${registered.get()}")
actionsToReceivers.forEach { (action, list) ->
- pw?.println(" $action:")
- list.forEach { pw?.println(" ${it.receiver}") }
+ pw.println(" $action:")
+ list.forEach { pw.println(" ${it.receiver}") }
}
}
@@ -161,17 +172,19 @@
val actionsToReceivers: Map<String, Set<ReceiverData>>,
val context: Context,
val intent: Intent,
- val pendingResult: PendingResult
+ val pendingResult: PendingResult,
+ val index: Int
) : Runnable {
override fun run() {
- if (DEBUG) Log.w(TAG, "Dispatching $intent")
+ if (DEBUG) Log.w(TAG, "[$index] Dispatching $intent")
actionsToReceivers.get(intent.action)
?.filter {
it.filter.hasAction(intent.action) &&
it.filter.matchCategories(intent.categories) == null }
?.forEach {
it.handler.post {
- if (DEBUG) Log.w(TAG, "Dispatching to ${it.receiver}")
+ if (DEBUG) Log.w(TAG,
+ "[$index] Dispatching ${intent.action} to ${it.receiver}")
it.receiver.pendingResult = pendingResult
it.receiver.onReceive(context, intent)
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
index 7600b2f..f8e45d4 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java
@@ -134,6 +134,10 @@
return mAppName;
}
+ public Drawable getUserBadgedAppIcon() {
+ return mUserBadgedAppIcon;
+ }
+
boolean isInflated() {
return mInflated;
}
@@ -165,7 +169,6 @@
mIconView = (BubbleView) inflater.inflate(
R.layout.bubble_view, stackView, false /* attachToRoot */);
mIconView.setBubble(this);
- mIconView.setAppIcon(mUserBadgedAppIcon);
mExpandedView = (BubbleExpandedView) inflater.inflate(
R.layout.bubble_expanded_view, stackView, false /* attachToRoot */);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index e5af389..4a1bbe4 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -1459,7 +1459,7 @@
mFlyout.setupFlyoutStartingAsDot(
updateMessage, mStackAnimationController.getStackPosition(), getWidth(),
mStackAnimationController.isStackOnLeftSide(),
- bubble.getIconView().getBadgeColor() /* dotColor */,
+ bubble.getIconView().getDotColor() /* dotColor */,
expandFlyoutAfterDelay /* onLayoutComplete */,
mFlyoutOnHide,
bubble.getIconView().getDotCenter());
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
index fe4fa90..35657d3 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
@@ -24,17 +24,16 @@
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Path;
-import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
-import android.graphics.drawable.InsetDrawable;
import android.util.AttributeSet;
import android.util.PathParser;
import android.widget.FrameLayout;
import com.android.internal.graphics.ColorUtils;
+import com.android.launcher3.icons.BitmapInfo;
+import com.android.launcher3.icons.ColorExtractor;
import com.android.launcher3.icons.ShadowGenerator;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -45,17 +44,13 @@
*/
public class BubbleView extends FrameLayout {
- private static final int DARK_ICON_ALPHA = 180;
- private static final double ICON_MIN_CONTRAST = 4.1;
- private static final int DEFAULT_BACKGROUND_COLOR = Color.LTGRAY;
// Same value as Launcher3 badge code
private static final float WHITE_SCRIM_ALPHA = 0.54f;
private Context mContext;
private BadgedImageView mBadgedImageView;
- private int mBadgeColor;
- private int mIconInset;
- private Drawable mUserBadgedAppIcon;
+ private int mDotColor;
+ private ColorExtractor mColorExtractor;
// mBubbleIconFactory cannot be static because it depends on Context.
private BubbleIconFactory mBubbleIconFactory;
@@ -79,13 +74,13 @@
public BubbleView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mContext = context;
- mIconInset = getResources().getDimensionPixelSize(R.dimen.bubble_icon_inset);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mBadgedImageView = findViewById(R.id.bubble_image);
+ mColorExtractor = new ColorExtractor();
}
@Override
@@ -106,6 +101,13 @@
}
/**
+ * @param factory Factory for creating normalized bubble icons.
+ */
+ public void setBubbleIconFactory(BubbleIconFactory factory) {
+ mBubbleIconFactory = factory;
+ }
+
+ /**
* The {@link NotificationEntry} associated with this view, if one exists.
*/
@Nullable
@@ -129,17 +131,6 @@
updateViews();
}
- /**
- * @param factory Factory for creating normalized bubble icons.
- */
- public void setBubbleIconFactory(BubbleIconFactory factory) {
- mBubbleIconFactory = factory;
- }
-
- public void setAppIcon(Drawable appIcon) {
- mUserBadgedAppIcon = appIcon;
- }
-
/** Changes the dot's visibility to match the bubble view's state. */
void updateDotVisibility(boolean animate) {
updateDotVisibility(animate, null /* after */);
@@ -154,9 +145,17 @@
updateDotVisibility(animate);
}
+ boolean isDotShowing() {
+ return mBubble.showBubbleDot() && !mSuppressDot;
+ }
+
+ int getDotColor() {
+ return mDotColor;
+ }
+
/** Sets the position of the 'new' dot, animating it out and back in if requested. */
void setDotPosition(boolean onLeft, boolean animate) {
- if (animate && onLeft != mBadgedImageView.getDotOnLeft() && shouldShowDot()) {
+ if (animate && onLeft != mBadgedImageView.getDotOnLeft() && isDotShowing()) {
animateDot(false /* showDot */, () -> {
mBadgedImageView.setDotOnLeft(onLeft);
animateDot(true /* showDot */, null);
@@ -180,7 +179,7 @@
* after animation if requested.
*/
private void updateDotVisibility(boolean animate, Runnable after) {
- final boolean showDot = shouldShowDot();
+ final boolean showDot = isDotShowing();
if (animate) {
animateDot(showDot, after);
} else {
@@ -218,42 +217,21 @@
if (mBubble == null || mBubbleIconFactory == null) {
return;
}
- // Update icon.
- Notification.BubbleMetadata metadata = mBubble.getEntry().getBubbleMetadata();
- Notification n = mBubble.getEntry().getSbn().getNotification();
- Icon ic = metadata.getIcon();
- boolean needsTint = ic.getType() != Icon.TYPE_ADAPTIVE_BITMAP;
- Drawable iconDrawable = ic.loadDrawable(mContext);
- if (needsTint) {
- iconDrawable = buildIconWithTint(iconDrawable, n.color);
- }
- Bitmap bubbleIcon = mBubbleIconFactory.createBadgedIconBitmap(iconDrawable,
- null /* user */,
- true /* shrinkNonAdaptiveIcons */).icon;
-
- // Give it a shadow
- Bitmap userBadgedBitmap = mBubbleIconFactory.createIconBitmap(mUserBadgedAppIcon,
- 1f, mBubbleIconFactory.getBadgeSize());
- Canvas c = new Canvas();
- ShadowGenerator shadowGenerator = new ShadowGenerator(mBubbleIconFactory.getBadgeSize());
- c.setBitmap(userBadgedBitmap);
- shadowGenerator.recreateIcon(Bitmap.createBitmap(userBadgedBitmap), c);
-
- mBubbleIconFactory.badgeWithDrawable(bubbleIcon,
- new BitmapDrawable(mContext.getResources(), userBadgedBitmap));
- mBadgedImageView.setImageBitmap(bubbleIcon);
+ Drawable bubbleDrawable = getBubbleDrawable(mContext);
+ BitmapInfo badgeBitmapInfo = getBadgedBitmap();
+ BitmapInfo bubbleBitmapInfo = getBubbleBitmap(bubbleDrawable, badgeBitmapInfo);
+ mBadgedImageView.setImageBitmap(bubbleBitmapInfo.icon);
// Update badge.
- int badgeColor = determineDominateColor(iconDrawable, n.color);
- mBadgeColor = badgeColor;
- mBadgedImageView.setDotColor(badgeColor);
+ mDotColor = ColorUtils.blendARGB(badgeBitmapInfo.color, Color.WHITE, WHITE_SCRIM_ALPHA);
+ mBadgedImageView.setDotColor(mDotColor);
// Update dot.
Path iconPath = PathParser.createPathFromPathData(
getResources().getString(com.android.internal.R.string.config_icon_mask));
Matrix matrix = new Matrix();
- float scale = mBubbleIconFactory.getNormalizer().getScale(iconDrawable,
+ float scale = mBubbleIconFactory.getNormalizer().getScale(bubbleDrawable,
null /* outBounds */, null /* path */, null /* outMaskShape */);
float radius = BadgedImageView.DEFAULT_PATH_SIZE / 2f;
matrix.setScale(scale /* x scale */, scale /* y scale */, radius /* pivot x */,
@@ -261,41 +239,34 @@
iconPath.transform(matrix);
mBadgedImageView.drawDot(iconPath);
- animateDot(shouldShowDot(), null /* after */);
+ animateDot(isDotShowing(), null /* after */);
}
- boolean shouldShowDot() {
- return mBubble.showBubbleDot() && !mSuppressDot;
+ Drawable getBubbleDrawable(Context context) {
+ Notification.BubbleMetadata metadata = getEntry().getBubbleMetadata();
+ Icon ic = metadata.getIcon();
+ return ic.loadDrawable(context);
}
- int getBadgeColor() {
- return mBadgeColor;
+ BitmapInfo getBadgedBitmap() {
+ Bitmap userBadgedBitmap = mBubbleIconFactory.createIconBitmap(
+ mBubble.getUserBadgedAppIcon(), 1f, mBubbleIconFactory.getBadgeSize());
+
+ Canvas c = new Canvas();
+ ShadowGenerator shadowGenerator = new ShadowGenerator(mBubbleIconFactory.getBadgeSize());
+ c.setBitmap(userBadgedBitmap);
+ shadowGenerator.recreateIcon(Bitmap.createBitmap(userBadgedBitmap), c);
+ BitmapInfo bitmapInfo = mBubbleIconFactory.createIconBitmap(userBadgedBitmap);
+ return bitmapInfo;
}
- private AdaptiveIconDrawable buildIconWithTint(Drawable iconDrawable, int backgroundColor) {
- iconDrawable = checkTint(iconDrawable, backgroundColor);
- InsetDrawable foreground = new InsetDrawable(iconDrawable, mIconInset);
- ColorDrawable background = new ColorDrawable(backgroundColor);
- return new AdaptiveIconDrawable(background, foreground);
- }
+ BitmapInfo getBubbleBitmap(Drawable bubble, BitmapInfo badge) {
+ BitmapInfo bubbleIconInfo = mBubbleIconFactory.createBadgedIconBitmap(bubble,
+ null /* user */,
+ true /* shrinkNonAdaptiveIcons */);
- private Drawable checkTint(Drawable iconDrawable, int backgroundColor) {
- backgroundColor = ColorUtils.setAlphaComponent(backgroundColor, 255 /* alpha */);
- if (backgroundColor == Color.TRANSPARENT) {
- // ColorUtils throws exception when background is translucent.
- backgroundColor = DEFAULT_BACKGROUND_COLOR;
- }
- iconDrawable.setTint(Color.WHITE);
- double contrastRatio = ColorUtils.calculateContrast(Color.WHITE, backgroundColor);
- if (contrastRatio < ICON_MIN_CONTRAST) {
- int dark = ColorUtils.setAlphaComponent(Color.BLACK, DARK_ICON_ALPHA);
- iconDrawable.setTint(dark);
- }
- return iconDrawable;
- }
-
- private int determineDominateColor(Drawable d, int defaultTint) {
- // XXX: should we pull from the drawable, app icon, notif tint?
- return ColorUtils.blendARGB(defaultTint, Color.WHITE, WHITE_SCRIM_ALPHA);
+ mBubbleIconFactory.badgeWithDrawable(bubbleIconInfo.icon,
+ new BitmapDrawable(mContext.getResources(), badge.icon));
+ return bubbleIconInfo;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ActivityBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/ActivityBinder.java
deleted file mode 100644
index 4be610f..0000000
--- a/packages/SystemUI/src/com/android/systemui/dagger/ActivityBinder.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.dagger;
-
-import android.app.Activity;
-
-import com.android.systemui.ForegroundServicesDialog;
-import com.android.systemui.tuner.TunerActivity;
-
-import dagger.Binds;
-import dagger.Module;
-import dagger.multibindings.ClassKey;
-import dagger.multibindings.IntoMap;
-
-/**
- * Services and Activities that are injectable should go here.
- */
-@Module
-public abstract class ActivityBinder {
- /** Inject into TunerActivity. */
- @Binds
- @IntoMap
- @ClassKey(TunerActivity.class)
- public abstract Activity bindTunerActivity(TunerActivity activity);
-
- /** Inject into ForegroundServicesDialog. */
- @Binds
- @IntoMap
- @ClassKey(ForegroundServicesDialog.class)
- public abstract Activity bindForegroundServicesDialog(ForegroundServicesDialog activity);
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.java b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.java
index d6d1e41..1e7449c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentHelper.java
@@ -18,8 +18,10 @@
import android.app.Activity;
import android.app.Service;
+import android.content.BroadcastReceiver;
import com.android.systemui.SystemUI;
+import com.android.systemui.recents.RecentsImplementation;
/**
* Interface necessary to make Dagger happy. See {@link ContextComponentResolver}.
@@ -29,8 +31,14 @@
Activity resolveActivity(String className);
/** Turns a classname into an instance of the class or returns null. */
+ RecentsImplementation resolveRecents(String className);
+
+ /** Turns a classname into an instance of the class or returns null. */
Service resolveService(String className);
/** Turns a classname into an instance of the class or returns null. */
SystemUI resolveSystemUI(String className);
+
+ /** Turns a classname into an instance of the class or returns null. */
+ BroadcastReceiver resolveBroadcastReceiver(String className);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java
index d7822c9..f91d795 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/ContextComponentResolver.java
@@ -18,8 +18,10 @@
import android.app.Activity;
import android.app.Service;
+import android.content.BroadcastReceiver;
import com.android.systemui.SystemUI;
+import com.android.systemui.recents.RecentsImplementation;
import java.util.Map;
@@ -35,15 +37,20 @@
private final Map<Class<?>, Provider<Activity>> mActivityCreators;
private final Map<Class<?>, Provider<Service>> mServiceCreators;
private final Map<Class<?>, Provider<SystemUI>> mSystemUICreators;
+ private final Map<Class<?>, Provider<RecentsImplementation>> mRecentsCreators;
+ private final Map<Class<?>, Provider<BroadcastReceiver>> mBroadcastReceiverCreators;
@Inject
- ContextComponentResolver(
- Map<Class<?>, Provider<Activity>> activityCreators,
+ ContextComponentResolver(Map<Class<?>, Provider<Activity>> activityCreators,
Map<Class<?>, Provider<Service>> serviceCreators,
- Map<Class<?>, Provider<SystemUI>> systemUICreators) {
+ Map<Class<?>, Provider<SystemUI>> systemUICreators,
+ Map<Class<?>, Provider<RecentsImplementation>> recentsCreators,
+ Map<Class<?>, Provider<BroadcastReceiver>> broadcastReceiverCreators) {
mActivityCreators = activityCreators;
mServiceCreators = serviceCreators;
mSystemUICreators = systemUICreators;
+ mRecentsCreators = recentsCreators;
+ mBroadcastReceiverCreators = broadcastReceiverCreators;
}
/**
@@ -55,6 +62,22 @@
}
/**
+ * Looks up the BroadcastReceiver class name to see if Dagger has an instance of it.
+ */
+ @Override
+ public BroadcastReceiver resolveBroadcastReceiver(String className) {
+ return resolve(className, mBroadcastReceiverCreators);
+ }
+
+ /**
+ * Looks up the RecentsImplementation class name to see if Dagger has an instance of it.
+ */
+ @Override
+ public RecentsImplementation resolveRecents(String className) {
+ return resolve(className, mRecentsCreators);
+ }
+
+ /**
* Looks up the Service class name to see if Dagger has an instance of it.
*/
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
new file mode 100644
index 0000000..4593164
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dagger;
+
+import android.app.Activity;
+
+import com.android.systemui.ForegroundServicesDialog;
+import com.android.systemui.keyguard.WorkLockActivity;
+import com.android.systemui.settings.BrightnessDialog;
+import com.android.systemui.tuner.TunerActivity;
+import com.android.systemui.usb.UsbDebuggingActivity;
+import com.android.systemui.usb.UsbDebuggingSecondaryUserActivity;
+
+import dagger.Binds;
+import dagger.Module;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
+
+/**
+ * Services and Activities that are injectable should go here.
+ */
+@Module
+public abstract class DefaultActivityBinder {
+ /** Inject into TunerActivity. */
+ @Binds
+ @IntoMap
+ @ClassKey(TunerActivity.class)
+ public abstract Activity bindTunerActivity(TunerActivity activity);
+
+ /** Inject into ForegroundServicesDialog. */
+ @Binds
+ @IntoMap
+ @ClassKey(ForegroundServicesDialog.class)
+ public abstract Activity bindForegroundServicesDialog(ForegroundServicesDialog activity);
+
+ /** Inject into WorkLockActivity. */
+ @Binds
+ @IntoMap
+ @ClassKey(WorkLockActivity.class)
+ public abstract Activity bindWorkLockActivity(WorkLockActivity activity);
+
+ /** Inject into BrightnessDialog. */
+ @Binds
+ @IntoMap
+ @ClassKey(BrightnessDialog.class)
+ public abstract Activity bindBrightnessDialog(BrightnessDialog activity);
+
+ /** Inject into UsbDebuggingActivity. */
+ @Binds
+ @IntoMap
+ @ClassKey(UsbDebuggingActivity.class)
+ public abstract Activity bindUsbDebuggingActivity(UsbDebuggingActivity activity);
+
+ /** Inject into UsbDebuggingSecondaryUserActivity. */
+ @Binds
+ @IntoMap
+ @ClassKey(UsbDebuggingSecondaryUserActivity.class)
+ public abstract Activity bindUsbDebuggingSecondaryUserActivity(
+ UsbDebuggingSecondaryUserActivity activity);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ComponentBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
similarity index 60%
copy from packages/SystemUI/src/com/android/systemui/dagger/ComponentBinder.java
copy to packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
index 4e4c06e..56d0fa2 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ComponentBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultBroadcastReceiverBinder.java
@@ -16,16 +16,24 @@
package com.android.systemui.dagger;
+import android.content.BroadcastReceiver;
+
+import com.android.systemui.screenshot.GlobalScreenshot.ActionProxyReceiver;
+
import dagger.Binds;
import dagger.Module;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
/**
- * Dagger Module that collects related sub-modules together.
+ * BroadcastReceivers that are injectable should go here.
*/
-@Module(includes = {ActivityBinder.class, ServiceBinder.class, SystemUIBinder.class})
-public abstract class ComponentBinder {
+@Module
+public abstract class DefaultBroadcastReceiverBinder {
/** */
@Binds
- public abstract ContextComponentHelper bindComponentHelper(
- ContextComponentResolver componentHelper);
+ @IntoMap
+ @ClassKey(ActionProxyReceiver.class)
+ public abstract BroadcastReceiver bindActionProxyReceiver(
+ ActionProxyReceiver broadcastReceiver);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ComponentBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultComponentBinder.java
similarity index 72%
rename from packages/SystemUI/src/com/android/systemui/dagger/ComponentBinder.java
rename to packages/SystemUI/src/com/android/systemui/dagger/DefaultComponentBinder.java
index 4e4c06e..18fe3ec 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ComponentBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultComponentBinder.java
@@ -16,16 +16,16 @@
package com.android.systemui.dagger;
-import dagger.Binds;
import dagger.Module;
/**
* Dagger Module that collects related sub-modules together.
+ *
+ * See {@link ContextComponentResolver}
*/
-@Module(includes = {ActivityBinder.class, ServiceBinder.class, SystemUIBinder.class})
-public abstract class ComponentBinder {
- /** */
- @Binds
- public abstract ContextComponentHelper bindComponentHelper(
- ContextComponentResolver componentHelper);
+@Module(includes = {DefaultActivityBinder.class,
+ DefaultBroadcastReceiverBinder.class,
+ DefaultServiceBinder.class,
+ SystemUIBinder.class})
+public abstract class DefaultComponentBinder {
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/ServiceBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java
similarity index 84%
rename from packages/SystemUI/src/com/android/systemui/dagger/ServiceBinder.java
rename to packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java
index 1f2c0a1..85cd51c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/ServiceBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java
@@ -21,6 +21,7 @@
import com.android.systemui.ImageWallpaper;
import com.android.systemui.doze.DozeService;
import com.android.systemui.keyguard.KeyguardService;
+import com.android.systemui.screenshot.TakeScreenshotService;
import dagger.Binds;
import dagger.Module;
@@ -31,7 +32,7 @@
* Services that are injectable should go here.
*/
@Module
-public abstract class ServiceBinder {
+public abstract class DefaultServiceBinder {
/** */
@Binds
@IntoMap
@@ -49,4 +50,10 @@
@IntoMap
@ClassKey(KeyguardService.class)
public abstract Service bindKeyguardService(KeyguardService service);
+
+ /** */
+ @Binds
+ @IntoMap
+ @ClassKey(TakeScreenshotService.class)
+ public abstract Service bindTakeScreenshotService(TakeScreenshotService service);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 87434f3..6d61b2f 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -27,12 +27,15 @@
import android.os.Looper;
import android.os.Process;
import android.os.ServiceManager;
+import android.os.UserManager;
import android.util.DisplayMetrics;
import android.view.IWindowManager;
+import android.view.LayoutInflater;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.BgHandler;
import com.android.systemui.dagger.qualifiers.BgLooper;
import com.android.systemui.dagger.qualifiers.MainHandler;
@@ -43,6 +46,7 @@
import com.android.systemui.shared.plugins.PluginManagerImpl;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.phone.AutoHideController;
@@ -152,6 +156,13 @@
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
}
+ /** */
+ @Singleton
+ @Provides
+ public LayoutInflater providerLayoutInflater(Context context) {
+ return LayoutInflater.from(context);
+ }
+
@Singleton
@Provides
public LeakDetector provideLeakDetector() {
@@ -181,8 +192,8 @@
@Singleton
@Provides
public NavigationBarController provideNavigationBarController(Context context,
- @MainHandler Handler mainHandler) {
- return new NavigationBarController(context, mainHandler);
+ @MainHandler Handler mainHandler, CommandQueue commandQueue) {
+ return new NavigationBarController(context, mainHandler, commandQueue);
}
@Singleton
@@ -216,8 +227,8 @@
@Singleton
@Provides
public DeviceProvisionedController provideDeviceProvisionedController(Context context,
- @MainHandler Handler mainHandler) {
- return new DeviceProvisionedControllerImpl(context, mainHandler);
+ @MainHandler Handler mainHandler, BroadcastDispatcher broadcastDispatcher) {
+ return new DeviceProvisionedControllerImpl(context, mainHandler, broadcastDispatcher);
}
/** */
@@ -231,4 +242,11 @@
public AlwaysOnDisplayPolicy provideAlwaysOnDisplayPolicy(Context context) {
return new AlwaysOnDisplayPolicy(context);
}
+
+ /** */
+ @Singleton
+ @Provides
+ public UserManager providesUserManager(Context context) {
+ return context.getSystemService(UserManager.class);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
index 738f539..3cf14d6 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
@@ -18,12 +18,23 @@
import com.android.systemui.LatencyTester;
import com.android.systemui.ScreenDecorations;
+import com.android.systemui.SizeCompatModeActivityController;
+import com.android.systemui.SliceBroadcastRelayHandler;
import com.android.systemui.SystemUI;
+import com.android.systemui.biometrics.AuthController;
+import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.pip.PipUI;
import com.android.systemui.power.PowerUI;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsModule;
+import com.android.systemui.shortcut.ShortcutKeyDispatcher;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.notification.InstantAppNotifier;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarModule;
+import com.android.systemui.statusbar.tv.TvStatusBar;
+import com.android.systemui.theme.ThemeOverlayController;
import com.android.systemui.util.leak.GarbageMonitor;
import com.android.systemui.volume.VolumeUI;
@@ -35,14 +46,37 @@
/**
* SystemUI objects that are injectable should go here.
*/
-@Module(includes = {RecentsModule.class})
+@Module(includes = {RecentsModule.class, StatusBarModule.class})
public abstract class SystemUIBinder {
+ /** Inject into AuthController. */
+ @Binds
+ @IntoMap
+ @ClassKey(AuthController.class)
+ public abstract SystemUI bindAuthController(AuthController service);
+
+ /** Inject into Divider. */
+ @Binds
+ @IntoMap
+ @ClassKey(Divider.class)
+ public abstract SystemUI bindDivider(Divider sysui);
/** Inject into GarbageMonitor.Service. */
@Binds
@IntoMap
@ClassKey(GarbageMonitor.Service.class)
- public abstract SystemUI bindGarbageMonitorService(GarbageMonitor.Service service);
+ public abstract SystemUI bindGarbageMonitorService(GarbageMonitor.Service sysui);
+
+ /** Inject into GlobalActionsComponent. */
+ @Binds
+ @IntoMap
+ @ClassKey(GlobalActionsComponent.class)
+ public abstract SystemUI bindGlobalActionsComponent(GlobalActionsComponent sysui);
+
+ /** Inject into InstantAppNotifier. */
+ @Binds
+ @IntoMap
+ @ClassKey(InstantAppNotifier.class)
+ public abstract SystemUI bindInstantAppNotifier(InstantAppNotifier sysui);
/** Inject into KeyguardViewMediator. */
@Binds
@@ -80,10 +114,46 @@
@ClassKey(ScreenDecorations.class)
public abstract SystemUI bindScreenDecorations(ScreenDecorations sysui);
+ /** Inject into ShortcutKeyDispatcher. */
+ @Binds
+ @IntoMap
+ @ClassKey(ShortcutKeyDispatcher.class)
+ public abstract SystemUI bindsShortcutKeyDispatcher(ShortcutKeyDispatcher sysui);
+
+ /** Inject into SizeCompatModeActivityController. */
+ @Binds
+ @IntoMap
+ @ClassKey(SizeCompatModeActivityController.class)
+ public abstract SystemUI bindsSizeCompatModeActivityController(
+ SizeCompatModeActivityController sysui);
+
+ /** Inject into SliceBroadcastRelayHandler. */
+ @Binds
+ @IntoMap
+ @ClassKey(SliceBroadcastRelayHandler.class)
+ public abstract SystemUI bindSliceBroadcastRelayHandler(SliceBroadcastRelayHandler sysui);
+
+ /** Inject into StatusBar. */
+ @Binds
+ @IntoMap
+ @ClassKey(StatusBar.class)
+ public abstract SystemUI bindsStatusBar(StatusBar sysui);
+
+ /** Inject into ThemeOverlayController. */
+ @Binds
+ @IntoMap
+ @ClassKey(ThemeOverlayController.class)
+ public abstract SystemUI bindThemeOverlayController(ThemeOverlayController sysui);
+
+ /** Inject into TvStatusBar. */
+ @Binds
+ @IntoMap
+ @ClassKey(TvStatusBar.class)
+ public abstract SystemUI bindsTvStatusBar(TvStatusBar sysui);
+
/** Inject into VolumeUI. */
@Binds
@IntoMap
@ClassKey(VolumeUI.class)
public abstract SystemUI bindVolumeUI(VolumeUI sysui);
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index c95b50b..fd2824d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -19,13 +19,15 @@
import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
+import android.content.Context;
+
import androidx.annotation.Nullable;
-import com.android.systemui.SystemUI;
import com.android.systemui.dock.DockManager;
import com.android.systemui.dock.DockManagerImpl;
import com.android.systemui.power.EnhancedEstimates;
import com.android.systemui.power.EnhancedEstimatesImpl;
+import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.notification.collection.NotificationData;
@@ -39,8 +41,6 @@
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
-import dagger.multibindings.ClassKey;
-import dagger.multibindings.IntoMap;
/**
* A dagger module for injecting default implementations of components of System UI that may be
@@ -74,15 +74,16 @@
@Binds
abstract ShadeController provideShadeController(StatusBar statusBar);
- @Binds
- @IntoMap
- @ClassKey(StatusBar.class)
- public abstract SystemUI providesStatusBar(StatusBar statusBar);
-
@Singleton
@Provides
@Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME)
static boolean provideAllowNotificationLongPress() {
return true;
}
+
+ @Singleton
+ @Provides
+ static Divider provideDivider(Context context) {
+ return new Divider(context);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 4e60f19..a248c7f 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -21,15 +21,21 @@
import android.content.pm.PackageManager;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.DumpController;
import com.android.systemui.assist.AssistModule;
import com.android.systemui.model.SysUiState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.notification.people.PeopleHubModule;
import com.android.systemui.statusbar.phone.KeyguardLiftController;
+import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.util.sensors.AsyncSensorManager;
import javax.inject.Singleton;
+import dagger.Binds;
+import dagger.BindsOptionalOf;
import dagger.Module;
import dagger.Provides;
@@ -38,9 +44,12 @@
* implementation.
*/
@Module(includes = {AssistModule.class,
- ComponentBinder.class,
PeopleHubModule.class})
public abstract class SystemUIModule {
+ /** */
+ @Binds
+ public abstract ContextComponentHelper bindComponentHelper(
+ ContextComponentResolver componentHelper);
@Singleton
@Provides
@@ -48,18 +57,27 @@
static KeyguardLiftController provideKeyguardLiftController(Context context,
StatusBarStateController statusBarStateController,
AsyncSensorManager asyncSensorManager,
- KeyguardUpdateMonitor keyguardUpdateMonitor) {
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ DumpController dumpController) {
if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
return null;
}
return new KeyguardLiftController(statusBarStateController, asyncSensorManager,
- keyguardUpdateMonitor);
+ keyguardUpdateMonitor, dumpController);
}
-
@Singleton
@Provides
static SysUiState provideSysUiState() {
return new SysUiState();
}
+
+ @BindsOptionalOf
+ abstract CommandQueue optionalCommandQueue();
+
+ @BindsOptionalOf
+ abstract Divider optionalDivider();
+
+ @BindsOptionalOf
+ abstract StatusBar optionalStatusBar();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java
index 113c9c8..83d956c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java
@@ -37,6 +37,7 @@
*/
@Singleton
@Component(modules = {
+ DefaultComponentBinder.class,
DependencyProvider.class,
DependencyBinder.class,
SystemServicesModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
index 33f68cf..71e1593 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java
@@ -18,7 +18,6 @@
import android.annotation.Nullable;
import android.app.AlarmManager;
-import android.app.Application;
import android.app.IWallpaperManager;
import android.content.Context;
import android.hardware.Sensor;
@@ -28,12 +27,13 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
-import com.android.systemui.SystemUIApplication;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dock.DockManager;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.sensors.AsyncSensorManager;
import com.android.systemui.util.sensors.ProximitySensor;
@@ -58,6 +58,8 @@
private final DelayedWakeLock.Builder mDelayedWakeLockBuilder;
private final Handler mHandler;
private final BiometricUnlockController mBiometricUnlockController;
+ private final BroadcastDispatcher mBroadcastDispatcher;
+ private final DozeServiceHost mDozeServiceHost;
@Inject
public DozeFactory(FalsingManager falsingManager, DozeLog dozeLog,
@@ -67,7 +69,8 @@
DockManager dockManager, @Nullable IWallpaperManager wallpaperManager,
ProximitySensor proximitySensor,
DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler,
- BiometricUnlockController biometricUnlockController) {
+ BiometricUnlockController biometricUnlockController,
+ BroadcastDispatcher broadcastDispatcher, DozeServiceHost dozeServiceHost) {
mFalsingManager = falsingManager;
mDozeLog = dozeLog;
mDozeParameters = dozeParameters;
@@ -82,16 +85,17 @@
mDelayedWakeLockBuilder = delayedWakeLockBuilder;
mHandler = handler;
mBiometricUnlockController = biometricUnlockController;
+ mBroadcastDispatcher = broadcastDispatcher;
+ mDozeServiceHost = dozeServiceHost;
}
/** Creates a DozeMachine with its parts for {@code dozeService}. */
DozeMachine assembleMachine(DozeService dozeService) {
- DozeHost host = getHost(dozeService);
AmbientDisplayConfiguration config = new AmbientDisplayConfiguration(dozeService);
WakeLock wakeLock = mDelayedWakeLockBuilder.setHandler(mHandler).setTag("Doze").build();
DozeMachine.Service wrappedService = dozeService;
- wrappedService = new DozeBrightnessHostForwarder(wrappedService, host);
+ wrappedService = new DozeBrightnessHostForwarder(wrappedService, mDozeServiceHost);
wrappedService = DozeScreenStatePreventingAdapter.wrapIfNeeded(
wrappedService, mDozeParameters);
wrappedService = DozeSuspendScreenStatePreventingAdapter.wrapIfNeeded(
@@ -102,16 +106,19 @@
machine.setParts(new DozeMachine.Part[]{
new DozePauser(mHandler, machine, mAlarmManager, mDozeParameters.getPolicy()),
new DozeFalsingManagerAdapter(mFalsingManager),
- createDozeTriggers(dozeService, mAsyncSensorManager, host, mAlarmManager, config,
- mDozeParameters, mHandler, wakeLock, machine, mDockManager, mDozeLog),
- createDozeUi(dozeService, host, wakeLock, machine, mHandler, mAlarmManager,
- mDozeParameters, mDozeLog),
- new DozeScreenState(wrappedService, mHandler, host, mDozeParameters, wakeLock),
- createDozeScreenBrightness(dozeService, wrappedService, mAsyncSensorManager, host,
- mDozeParameters, mHandler),
- new DozeWallpaperState(
- mWallpaperManager, mBiometricUnlockController, mDozeParameters),
- new DozeDockHandler(dozeService, machine, host, config, mHandler, mDockManager),
+ createDozeTriggers(dozeService, mAsyncSensorManager, mDozeServiceHost,
+ mAlarmManager, config, mDozeParameters, mHandler, wakeLock, machine,
+ mDockManager, mDozeLog),
+ createDozeUi(dozeService, mDozeServiceHost, wakeLock, machine, mHandler,
+ mAlarmManager, mDozeParameters, mDozeLog),
+ new DozeScreenState(wrappedService, mHandler, mDozeServiceHost, mDozeParameters,
+ wakeLock),
+ createDozeScreenBrightness(dozeService, wrappedService, mAsyncSensorManager,
+ mDozeServiceHost, mDozeParameters, mHandler),
+ new DozeWallpaperState(mWallpaperManager, mBiometricUnlockController,
+ mDozeParameters),
+ new DozeDockHandler(dozeService, machine, mDozeServiceHost, config, mHandler,
+ mDockManager),
new DozeAuthRemover(dozeService)
});
@@ -123,8 +130,8 @@
DozeParameters params, Handler handler) {
Sensor sensor = DozeSensors.findSensorWithType(sensorManager,
context.getString(R.string.doze_brightness_sensor_type));
- return new DozeScreenBrightness(context, service, sensorManager, sensor, host, handler,
- params.getPolicy());
+ return new DozeScreenBrightness(context, service, sensorManager, sensor,
+ mBroadcastDispatcher, host, handler, params.getPolicy());
}
private DozeTriggers createDozeTriggers(Context context, AsyncSensorManager sensorManager,
@@ -134,7 +141,7 @@
boolean allowPulseTriggers = true;
return new DozeTriggers(context, machine, host, alarmManager, config, params,
sensorManager, handler, wakeLock, allowPulseTriggers, dockManager,
- mProximitySensor, dozeLog);
+ mProximitySensor, dozeLog, mBroadcastDispatcher);
}
@@ -144,10 +151,4 @@
return new DozeUi(context, alarmManager, machine, wakeLock, host, handler, params,
mKeyguardUpdateMonitor, dozeLog);
}
-
- public static DozeHost getHost(DozeService service) {
- Application appCandidate = service.getApplication();
- final SystemUIApplication app = (SystemUIApplication) appCandidate;
- return app.getComponent(DozeHost.class);
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index bd6882c..39a2562 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -31,6 +31,7 @@
import android.provider.Settings;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.broadcast.BroadcastDispatcher;
/**
* Controls the screen brightness when dozing.
@@ -49,6 +50,7 @@
private final Handler mHandler;
private final SensorManager mSensorManager;
private final Sensor mLightSensor;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private final int[] mSensorToBrightness;
private final int[] mSensorToScrimOpacity;
private final boolean mDebuggable;
@@ -69,13 +71,15 @@
@VisibleForTesting
public DozeScreenBrightness(Context context, DozeMachine.Service service,
- SensorManager sensorManager, Sensor lightSensor, DozeHost host,
+ SensorManager sensorManager, Sensor lightSensor,
+ BroadcastDispatcher broadcastDispatcher, DozeHost host,
Handler handler, int defaultDozeBrightness, int[] sensorToBrightness,
int[] sensorToScrimOpacity, boolean debuggable) {
mContext = context;
mDozeService = service;
mSensorManager = sensorManager;
mLightSensor = lightSensor;
+ mBroadcastDispatcher = broadcastDispatcher;
mDozeHost = host;
mHandler = handler;
mDebuggable = debuggable;
@@ -87,14 +91,15 @@
if (mDebuggable) {
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_AOD_BRIGHTNESS);
- mContext.registerReceiverAsUser(this, UserHandle.ALL, filter, null, handler);
+ mBroadcastDispatcher.registerReceiver(this, filter, handler, UserHandle.ALL);
}
}
public DozeScreenBrightness(Context context, DozeMachine.Service service,
- SensorManager sensorManager, Sensor lightSensor, DozeHost host,
- Handler handler, AlwaysOnDisplayPolicy policy) {
- this(context, service, sensorManager, lightSensor, host, handler,
+ SensorManager sensorManager, Sensor lightSensor,
+ BroadcastDispatcher broadcastDispatcher, DozeHost host, Handler handler,
+ AlwaysOnDisplayPolicy policy) {
+ this(context, service, sensorManager, lightSensor, broadcastDispatcher, host, handler,
context.getResources().getInteger(
com.android.internal.R.integer.config_screenBrightnessDoze),
policy.screenBrightnessArray, policy.dimmingScrimArray, DEBUG_AOD_BRIGHTNESS);
@@ -127,7 +132,7 @@
private void onDestroy() {
setLightSensorEnabled(false);
if (mDebuggable) {
- mContext.unregisterReceiver(this);
+ mBroadcastDispatcher.unregisterReceiver(this);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 08734d2..7cbbdd7 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -55,10 +55,6 @@
setWindowless(true);
- if (DozeFactory.getHost(this) == null) {
- finish();
- return;
- }
mPluginManager.addPluginListener(this, DozeServicePlugin.class, false /* allowMultiple */);
mDozeMachine = mDozeFactory.assembleMachine(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index b212884..1134268 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -36,6 +36,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.Dependency;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dock.DockManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.Assert;
@@ -80,6 +81,7 @@
private final DockEventListener mDockEventListener = new DockEventListener();
private final DockManager mDockManager;
private final ProximitySensor.ProximityCheck mProxCheck;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private long mNotificationPulseTime;
private boolean mPulsePending;
@@ -91,7 +93,7 @@
DozeParameters dozeParameters, AsyncSensorManager sensorManager, Handler handler,
WakeLock wakeLock, boolean allowPulseTriggers, DockManager dockManager,
ProximitySensor proximitySensor,
- DozeLog dozeLog) {
+ DozeLog dozeLog, BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mMachine = machine;
mDozeHost = dozeHost;
@@ -107,6 +109,7 @@
mDockManager = dockManager;
mProxCheck = new ProximitySensor.ProximityCheck(proximitySensor, handler);
mDozeLog = dozeLog;
+ mBroadcastDispatcher = broadcastDispatcher;
}
private void onNotification(Runnable onPulseSuppressedListener) {
@@ -299,7 +302,7 @@
public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
switch (newState) {
case INITIALIZED:
- mBroadcastReceiver.register(mContext);
+ mBroadcastReceiver.register(mBroadcastDispatcher);
mDozeHost.addCallback(mHostCallback);
if (mDockManager != null) {
mDockManager.addListener(mDockEventListener);
@@ -334,7 +337,7 @@
mDozeSensors.updateListening();
break;
case FINISH:
- mBroadcastReceiver.unregister(mContext);
+ mBroadcastReceiver.unregister(mBroadcastDispatcher);
mDozeHost.removeCallback(mHostCallback);
if (mDockManager != null) {
mDockManager.removeListener(mDockEventListener);
@@ -437,22 +440,22 @@
}
}
- public void register(Context context) {
+ public void register(BroadcastDispatcher broadcastDispatcher) {
if (mRegistered) {
return;
}
IntentFilter filter = new IntentFilter(PULSE_ACTION);
filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
filter.addAction(Intent.ACTION_USER_SWITCHED);
- context.registerReceiver(this, filter);
+ broadcastDispatcher.registerReceiver(this, filter);
mRegistered = true;
}
- public void unregister(Context context) {
+ public void unregister(BroadcastDispatcher broadcastDispatcher) {
if (!mRegistered) {
return;
}
- context.unregisterReceiver(this);
+ broadcastDispatcher.unregisterReceiver(this);
mRegistered = false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
index c11127d..19b6f82 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
@@ -20,7 +20,6 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.Dependency;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.SystemUI;
import com.android.systemui.plugins.GlobalActions;
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
@@ -29,14 +28,24 @@
import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.ExtensionController.Extension;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Manages power menu plugins and communicates power menu actions to the StatusBar.
+ */
+@Singleton
public class GlobalActionsComponent extends SystemUI implements Callbacks, GlobalActionsManager {
+ private final CommandQueue mCommandQueue;
private GlobalActions mPlugin;
private Extension<GlobalActions> mExtension;
private IStatusBarService mBarService;
- public GlobalActionsComponent(Context context) {
+ @Inject
+ public GlobalActionsComponent(Context context, CommandQueue commandQueue) {
super(context);
+ mCommandQueue = commandQueue;
}
@Override
@@ -45,11 +54,11 @@
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mExtension = Dependency.get(ExtensionController.class).newExtension(GlobalActions.class)
.withPlugin(GlobalActions.class)
- .withDefault(() -> new GlobalActionsImpl(mContext))
+ .withDefault(() -> new GlobalActionsImpl(mContext, mCommandQueue))
.withCallback(this::onExtensionCallback)
.build();
mPlugin = mExtension.get();
- SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this);
+ mCommandQueue.addCallback(this);
}
private void onExtensionCallback(GlobalActions newPlugin) {
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 22846bc..bb2d142 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -52,6 +52,7 @@
import android.provider.Settings;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
+import android.telecom.TelecomManager;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
@@ -145,6 +146,7 @@
private final DevicePolicyManager mDevicePolicyManager;
private final LockPatternUtils mLockPatternUtils;
private final KeyguardManager mKeyguardManager;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private ArrayList<Action> mItems;
private ActionsDialog mDialog;
@@ -182,13 +184,14 @@
Context.DEVICE_POLICY_SERVICE);
mLockPatternUtils = new LockPatternUtils(mContext);
mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+ mBroadcastDispatcher = Dependency.get(BroadcastDispatcher.class);
// receive broadcasts
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
- Dependency.get(BroadcastDispatcher.class).registerReceiver(mBroadcastReceiver, filter);
+ mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter);
ConnectivityManager cm = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -563,7 +566,8 @@
@Override
public void onPress() {
MetricsLogger.action(mContext, MetricsEvent.ACTION_EMERGENCY_DIALER_FROM_POWER_MENU);
- Intent intent = new Intent(EmergencyDialerConstants.ACTION_DIAL);
+ Intent intent = mContext.getSystemService(TelecomManager.class)
+ .createLaunchEmergencyDialerIntent(null /* number */);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
@@ -899,7 +903,7 @@
mAdapter.notifyDataSetChanged();
if (mShowSilentToggle) {
IntentFilter filter = new IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION);
- mContext.registerReceiver(mRingerModeReceiver, filter);
+ mBroadcastDispatcher.registerReceiver(mRingerModeReceiver, filter);
}
}
@@ -917,7 +921,7 @@
mWindowManagerFuncs.onGlobalActionsHidden();
if (mShowSilentToggle) {
try {
- mContext.unregisterReceiver(mRingerModeReceiver);
+ mBroadcastDispatcher.unregisterReceiver(mRingerModeReceiver);
} catch (IllegalArgumentException ie) {
// ignore this
Log.w(TAG, ie);
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index b9fe827..d5f5a5a 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -33,16 +33,18 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.GlobalActions;
import com.android.systemui.plugins.GlobalActionsPanelPlugin;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
-public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks {
+public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks,
+ PluginListener<GlobalActionsPanelPlugin> {
private static final float SHUTDOWN_SCRIM_ALPHA = 0.95f;
@@ -50,23 +52,35 @@
private final KeyguardStateController mKeyguardStateController;
private final DeviceProvisionedController mDeviceProvisionedController;
private final ExtensionController.Extension<GlobalActionsPanelPlugin> mPanelExtension;
+ private GlobalActionsPanelPlugin mPlugin;
+ private final CommandQueue mCommandQueue;
private GlobalActionsDialog mGlobalActions;
private boolean mDisabled;
+ private final PluginManager mPluginManager;
+ private final String mPluginPackageName;
- public GlobalActionsImpl(Context context) {
+ public GlobalActionsImpl(Context context, CommandQueue commandQueue) {
mContext = context;
mKeyguardStateController = Dependency.get(KeyguardStateController.class);
mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
- SysUiServiceProvider.getComponent(context, CommandQueue.class).addCallback(this);
+ mPluginManager = Dependency.get(PluginManager.class);
+ mCommandQueue = commandQueue;
+ mCommandQueue.addCallback(this);
mPanelExtension = Dependency.get(ExtensionController.class)
.newExtension(GlobalActionsPanelPlugin.class)
.withPlugin(GlobalActionsPanelPlugin.class)
.build();
+ mPluginPackageName = mContext.getString(
+ com.android.systemui.R.string.config_controlsPluginPackageName);
+ mPluginManager.addPluginListener(
+ GlobalActionsPanelPlugin.ACTION, this, GlobalActionsPanelPlugin.class, true);
}
@Override
public void destroy() {
- SysUiServiceProvider.getComponent(mContext, CommandQueue.class).removeCallback(this);
+ mCommandQueue.removeCallback(this);
+ mPluginManager.removePluginListener(this);
+ if (mPlugin != null) mPlugin.onDestroy();
if (mGlobalActions != null) {
mGlobalActions.destroy();
mGlobalActions = null;
@@ -81,7 +95,7 @@
}
mGlobalActions.showDialog(mKeyguardStateController.isShowing(),
mDeviceProvisionedController.isDeviceProvisioned(),
- mPanelExtension.get());
+ mPlugin != null ? mPlugin : mPanelExtension.get());
Dependency.get(KeyguardUpdateMonitor.class).requestFaceAuth();
}
@@ -144,4 +158,16 @@
mGlobalActions.dismissDialog();
}
}
+
+ @Override
+ public void onPluginConnected(GlobalActionsPanelPlugin plugin, Context pluginContext) {
+ if (pluginContext.getPackageName().equals(mPluginPackageName)) {
+ mPlugin = plugin;
+ }
+ }
+
+ @Override
+ public void onPluginDisconnected(GlobalActionsPanelPlugin plugin) {
+ mPlugin = null;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 411bf9a..3b1edcc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -87,6 +87,7 @@
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.UiOffloadThread;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -319,6 +320,7 @@
*/
private boolean mWaitingUntilKeyguardVisible = false;
private final LockPatternUtils mLockPatternUtils;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private boolean mKeyguardDonePending = false;
private boolean mHideAnimationRun = false;
private boolean mHideAnimationRunning = false;
@@ -685,8 +687,10 @@
public KeyguardViewMediator(
Context context,
FalsingManager falsingManager,
- LockPatternUtils lockPatternUtils) {
- this(context, falsingManager, lockPatternUtils, SystemUIFactory.getInstance());
+ LockPatternUtils lockPatternUtils,
+ BroadcastDispatcher broadcastDispatcher) {
+ this(context, falsingManager, lockPatternUtils, broadcastDispatcher,
+ SystemUIFactory.getInstance());
}
@VisibleForTesting
@@ -694,10 +698,12 @@
Context context,
FalsingManager falsingManager,
LockPatternUtils lockPatternUtils,
+ BroadcastDispatcher broadcastDispatcher,
SystemUIFactory systemUIFactory) {
super(context);
mFalsingManager = falsingManager;
mLockPatternUtils = lockPatternUtils;
+ mBroadcastDispatcher = broadcastDispatcher;
mStatusBarKeyguardViewManager = systemUIFactory.createStatusBarKeyguardViewManager(
mContext,
mViewMediatorCallback,
@@ -722,7 +728,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SHUTDOWN);
- mContext.registerReceiver(mBroadcastReceiver, filter);
+ mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter);
final IntentFilter delayedActionFilter = new IntentFilter();
delayedActionFilter.addAction(DELAYED_KEYGUARD_ACTION);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
index 4d061e1..ca04633 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WorkLockActivity.java
@@ -36,6 +36,9 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+
+import javax.inject.Inject;
/**
* Bouncer between work activities and the activity used to confirm credentials before unlocking
@@ -67,14 +70,21 @@
* @see KeyguardManager
*/
private KeyguardManager mKgm;
+ private final BroadcastDispatcher mBroadcastDispatcher;
+
+ @Inject
+ public WorkLockActivity(BroadcastDispatcher broadcastDispatcher) {
+ super();
+ mBroadcastDispatcher = broadcastDispatcher;
+ }
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- registerReceiverAsUser(mLockEventReceiver, UserHandle.ALL,
- new IntentFilter(Intent.ACTION_DEVICE_LOCKED_CHANGED), /* permission */ null,
- /* scheduler */ null);
+ mBroadcastDispatcher.registerReceiver(mLockEventReceiver,
+ new IntentFilter(Intent.ACTION_DEVICE_LOCKED_CHANGED), null /* handler */,
+ UserHandle.ALL);
// Once the receiver is registered, check whether anything happened between now and the time
// when this activity was launched. If it did and the user is unlocked now, just quit.
@@ -107,9 +117,14 @@
}
}
+ @VisibleForTesting
+ protected void unregisterBroadcastReceiver() {
+ mBroadcastDispatcher.unregisterReceiver(mLockEventReceiver);
+ }
+
@Override
public void onDestroy() {
- unregisterReceiver(mLockEventReceiver);
+ unregisterBroadcastReceiver();
super.onDestroy();
}
@@ -160,7 +175,12 @@
credential.putExtra(EXTRA_FROM_WORK_LOCK_ACTIVITY, true);
}
- startActivityForResult(credential, REQUEST_CODE_CONFIRM_CREDENTIALS);
+ final ActivityOptions launchOptions = ActivityOptions.makeBasic();
+ launchOptions.setLaunchTaskId(getTaskId());
+ launchOptions.setTaskOverlay(true /* taskOverlay */, true /* canResume */);
+
+ startActivityForResult(credential, REQUEST_CODE_CONFIRM_CREDENTIALS,
+ launchOptions.toBundle());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/log/RichEvent.java b/packages/SystemUI/src/com/android/systemui/log/RichEvent.java
index 89b7a818..acf761ed 100644
--- a/packages/SystemUI/src/com/android/systemui/log/RichEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/log/RichEvent.java
@@ -67,7 +67,7 @@
private B mBuilder = getBuilder();
protected int mType = UNINITIALIZED;
protected String mReason;
- protected @Level int mLogLevel;
+ protected @Level int mLogLevel = VERBOSE;
/**
* Get the log-specific builder.
diff --git a/packages/SystemUI/src/com/android/systemui/log/SysuiLog.java b/packages/SystemUI/src/com/android/systemui/log/SysuiLog.java
index a6e10e6..f094cb9 100644
--- a/packages/SystemUI/src/com/android/systemui/log/SysuiLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/SysuiLog.java
@@ -120,9 +120,9 @@
}
/**
- * @return user-readable string of the given event
+ * @return user-readable string of the given event with timestamp
*/
- public String eventToString(Event event) {
+ public String eventToTimestampedString(Event event) {
StringBuilder sb = new StringBuilder();
sb.append(SysuiLog.DATE_FORMAT.format(event.getTimestamp()));
sb.append(" ");
@@ -131,13 +131,20 @@
}
/**
+ * @return user-readable string of the given event without a timestamp
+ */
+ public String eventToString(Event event) {
+ return event.getMessage();
+ }
+
+ /**
* only call on this method if you have the mDataLock
*/
private void dumpTimelineLocked(PrintWriter pw) {
pw.println("\tTimeline:");
for (Event event : mTimeline) {
- pw.println("\t" + eventToString(event));
+ pw.println("\t" + eventToTimestampedString(event));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
index 05be425..75e260e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/BasePipManager.java
@@ -19,10 +19,12 @@
import android.content.Context;
import android.content.res.Configuration;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+
import java.io.PrintWriter;
public interface BasePipManager {
- void initialize(Context context);
+ void initialize(Context context, BroadcastDispatcher broadcastDispatcher);
void showPictureInPictureMenu();
default void expandPip() {}
default void hidePipMenu(Runnable onStartCallback, Runnable onEndCallback) {}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
index f1e801b..583ce67 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipUI.java
@@ -26,6 +26,7 @@
import android.os.UserManager;
import com.android.systemui.SystemUI;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.statusbar.CommandQueue;
import java.io.FileDescriptor;
@@ -40,13 +41,18 @@
@Singleton
public class PipUI extends SystemUI implements CommandQueue.Callbacks {
+ private final CommandQueue mCommandQueue;
private BasePipManager mPipManager;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private boolean mSupportsPip;
@Inject
- public PipUI(Context context) {
+ public PipUI(Context context, CommandQueue commandQueue,
+ BroadcastDispatcher broadcastDispatcher) {
super(context);
+ mBroadcastDispatcher = broadcastDispatcher;
+ mCommandQueue = commandQueue;
}
@Override
@@ -66,9 +72,9 @@
mPipManager = pm.hasSystemFeature(FEATURE_LEANBACK_ONLY)
? com.android.systemui.pip.tv.PipManager.getInstance()
: com.android.systemui.pip.phone.PipManager.getInstance();
- mPipManager.initialize(mContext);
+ mPipManager.initialize(mContext, mBroadcastDispatcher);
- getComponent(CommandQueue.class).addCallback(this);
+ mCommandQueue.addCallback(this);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 369073c..c33b8d9 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -37,6 +37,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.UiOffloadThread;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.pip.BasePipManager;
import com.android.systemui.pip.PipBoundsHandler;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -200,7 +201,7 @@
/**
* Initializes {@link PipManager}.
*/
- public void initialize(Context context) {
+ public void initialize(Context context, BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mActivityManager = ActivityManager.getService();
mActivityTaskManager = ActivityTaskManager.getService();
@@ -214,7 +215,7 @@
mPipBoundsHandler = new PipBoundsHandler(context);
mInputConsumerController = InputConsumerController.getPipInputConsumer();
- mMediaController = new PipMediaController(context, mActivityManager);
+ mMediaController = new PipMediaController(context, mActivityManager, broadcastDispatcher);
mMenuController = new PipMenuActivityController(context, mActivityManager, mMediaController,
mInputConsumerController);
mTouchHandler = new PipTouchHandler(context, mActivityManager, mActivityTaskManager,
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
index 174a7ef..e57b416 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMediaController.java
@@ -37,6 +37,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.statusbar.policy.UserInfoController;
import java.util.ArrayList;
@@ -109,7 +110,8 @@
private ArrayList<ActionListener> mListeners = new ArrayList<>();
- public PipMediaController(Context context, IActivityManager activityManager) {
+ public PipMediaController(Context context, IActivityManager activityManager,
+ BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mActivityManager = activityManager;
IntentFilter mediaControlFilter = new IntentFilter();
@@ -117,7 +119,7 @@
mediaControlFilter.addAction(ACTION_PAUSE);
mediaControlFilter.addAction(ACTION_NEXT);
mediaControlFilter.addAction(ACTION_PREV);
- mContext.registerReceiver(mPlayPauseActionReceiver, mediaControlFilter);
+ broadcastDispatcher.registerReceiver(mPlayPauseActionReceiver, mediaControlFilter);
createMediaActions();
mMediaSessionManager =
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 81d6973..195fca8 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -48,6 +48,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.UiOffloadThread;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.pip.BasePipManager;
import com.android.systemui.pip.PipBoundsHandler;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -227,7 +228,7 @@
/**
* Initializes {@link PipManager}.
*/
- public void initialize(Context context) {
+ public void initialize(Context context, BroadcastDispatcher broadcastDispatcher) {
if (mInitialized) {
return;
}
@@ -238,8 +239,8 @@
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_MEDIA_RESOURCE_GRANTED);
- mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, intentFilter,
- null, null);
+ broadcastDispatcher.registerReceiver(mBroadcastReceiver, intentFilter,
+ null /* handler */, UserHandle.ALL);
if (sSettingsPackageAndClassNamePairList == null) {
String[] settings = mContext.getResources().getStringArray(
@@ -286,7 +287,7 @@
Log.e(TAG, "Failed to register pinned stack listener", e);
}
- mPipNotification = new PipNotification(context);
+ mPipNotification = new PipNotification(context, broadcastDispatcher);
}
private void loadConfigurationsAndApply(Configuration newConfig) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
index d50f294e4..ca15131 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
@@ -34,6 +34,7 @@
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.util.NotificationChannels;
/**
@@ -143,7 +144,7 @@
}
};
- public PipNotification(Context context) {
+ public PipNotification(Context context, BroadcastDispatcher broadcastDispatcher) {
mNotificationManager = (NotificationManager) context.getSystemService(
Context.NOTIFICATION_SERVICE);
@@ -161,7 +162,7 @@
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ACTION_MENU);
intentFilter.addAction(ACTION_CLOSE);
- context.registerReceiver(mEventReceiver, intentFilter);
+ broadcastDispatcher.registerReceiver(mEventReceiver, intentFilter);
onConfigurationChanged(context);
}
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index 22fb4c0..d592492 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -22,7 +22,11 @@
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
-import android.os.*
+import android.os.Handler
+import android.os.Looper
+import android.os.Message
+import android.os.UserHandle
+import android.os.UserManager
import android.provider.DeviceConfig
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
@@ -30,6 +34,7 @@
import com.android.systemui.R
import com.android.systemui.appops.AppOpItem
import com.android.systemui.appops.AppOpsController
+import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.qualifiers.BgHandler
import com.android.systemui.dagger.qualifiers.MainHandler
import java.io.FileDescriptor
@@ -43,10 +48,11 @@
@Singleton
class PrivacyItemController @Inject constructor(
- val context: Context,
+ private val context: Context,
private val appOpsController: AppOpsController,
@MainHandler private val uiHandler: Handler,
- @BgHandler private val bgHandler: Handler
+ @BgHandler private val bgHandler: Handler,
+ private val broadcastDispatcher: BroadcastDispatcher
) : Dumpable {
@VisibleForTesting
@@ -134,15 +140,15 @@
}
private fun unregisterReceiver() {
- context.unregisterReceiver(userSwitcherReceiver)
+ broadcastDispatcher.unregisterReceiver(userSwitcherReceiver)
}
private fun registerReceiver() {
- context.registerReceiverAsUser(userSwitcherReceiver, UserHandle.ALL, IntentFilter().apply {
+ broadcastDispatcher.registerReceiver(userSwitcherReceiver, IntentFilter().apply {
intents.forEach {
addAction(it)
}
- }, null, null)
+ }, null /* handler */, UserHandle.ALL)
}
private fun update(updateUsers: Boolean) {
@@ -248,20 +254,20 @@
}
}
- override fun dump(fd: FileDescriptor?, pw: PrintWriter?, args: Array<out String>?) {
- pw?.println("PrivacyItemController state:")
- pw?.println(" Listening: $listening")
- pw?.println(" Current user ids: $currentUserIds")
- pw?.println(" Privacy Items:")
+ override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
+ pw.println("PrivacyItemController state:")
+ pw.println(" Listening: $listening")
+ pw.println(" Current user ids: $currentUserIds")
+ pw.println(" Privacy Items:")
privacyList.forEach {
- pw?.print(" ")
- pw?.println(it.toString())
+ pw.print(" ")
+ pw.println(it.toString())
}
- pw?.println(" Callbacks:")
+ pw.println(" Callbacks:")
callbacks.forEach {
it.get()?.let {
- pw?.print(" ")
- pw?.println(it.toString())
+ pw.print(" ")
+ pw.println(it.toString())
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index a267bbb..a0ea7fa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -14,7 +14,6 @@
package com.android.systemui.qs;
-import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
@@ -31,6 +30,7 @@
import com.android.systemui.qs.TouchAnimator.Listener;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
+import com.android.systemui.util.Utils;
import java.util.ArrayList;
import java.util.Collection;
@@ -270,9 +270,7 @@
}
- int flag = Settings.System.getInt(mQsPanel.getContext().getContentResolver(),
- "qs_media_player", 0);
- if (flag == 1) {
+ if (Utils.useQsMediaPlayer(mQsPanel.getContext())) {
View qsMediaView = mQsPanel.getMediaPanel();
View qqsMediaView = mQuickQsPanel.getMediaPlayer().getView();
translationXBuilder.addFloat(qsMediaView, "alpha", 0, 1);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 496aa0e..60d30da 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -38,7 +38,6 @@
import com.android.systemui.Dependency;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.statusbar.CommandQueue;
@@ -169,8 +168,7 @@
setupDetailHeader(adapter);
if (toggleQs && !mFullyExpanded) {
mTriggeredExpand = true;
- SysUiServiceProvider.getComponent(mContext, CommandQueue.class)
- .animateExpandSettingsPanel(null);
+ Dependency.get(CommandQueue.class).animateExpandSettingsPanel(null);
} else {
mTriggeredExpand = false;
}
@@ -181,8 +179,7 @@
x = mOpenX;
y = mOpenY;
if (toggleQs && mTriggeredExpand) {
- SysUiServiceProvider.getComponent(mContext, CommandQueue.class)
- .animateCollapsePanels();
+ Dependency.get(CommandQueue.class).animateCollapsePanels();
mTriggeredExpand = false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 0a3b43a..ccc836f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -38,7 +38,6 @@
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.R.id;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.customize.QSCustomizer;
@@ -97,11 +96,10 @@
InjectionInflationController injectionInflater,
Context context,
QSTileHost qsTileHost,
- StatusBarStateController statusBarStateController) {
+ StatusBarStateController statusBarStateController, CommandQueue commandQueue) {
mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
mInjectionInflater = injectionInflater;
- SysUiServiceProvider.getComponent(context, CommandQueue.class)
- .observe(getLifecycle(), this);
+ commandQueue.observe(getLifecycle(), this);
mHost = qsTileHost;
mStatusBarStateController = statusBarStateController;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index b48814b..cac9025 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -18,6 +18,7 @@
import static com.android.systemui.qs.tileimpl.QSTileImpl.getColorForState;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
+import static com.android.systemui.util.Utils.useQsMediaPlayer;
import android.annotation.Nullable;
import android.content.ComponentName;
@@ -49,6 +50,7 @@
import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.plugins.qs.QSTileView;
@@ -124,12 +126,13 @@
}
public QSPanel(Context context, AttributeSet attrs, DumpController dumpController) {
- this(context, attrs, dumpController, null);
+ this(context, attrs, dumpController, null, Dependency.get(BroadcastDispatcher.class));
}
@Inject
public QSPanel(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
- DumpController dumpController, PluginManager pluginManager) {
+ DumpController dumpController, PluginManager pluginManager,
+ BroadcastDispatcher broadcastDispatcher) {
super(context, attrs);
mContext = context;
@@ -150,8 +153,7 @@
addDivider();
// Add media carousel
- int flag = Settings.System.getInt(context.getContentResolver(), "qs_media_player", 0);
- if (flag == 1) {
+ if (useQsMediaPlayer(context)) {
HorizontalScrollView mediaScrollView = new HorizontalScrollView(mContext);
mediaScrollView.setHorizontalScrollBarEnabled(false);
int playerHeight = (int) getResources().getDimension(R.dimen.qs_media_height);
@@ -177,7 +179,7 @@
updateResources();
mBrightnessController = new BrightnessController(getContext(),
- findViewById(R.id.brightness_slider));
+ findViewById(R.id.brightness_slider), broadcastDispatcher);
mDumpController = dumpController;
mPluginManager = pluginManager;
if (mPluginManager != null && Settings.System.getInt(
@@ -201,8 +203,7 @@
*/
public void addMediaSession(MediaSession.Token token, Icon icon, int iconColor, int bgColor,
View actionsContainer, StatusBarNotification notif) {
- int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0);
- if (flag != 1) {
+ if (!useQsMediaPlayer(mContext)) {
// Shouldn't happen, but just in case
Log.e(TAG, "Tried to add media session without player!");
return;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index b395c3c..6d434b1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -34,6 +34,7 @@
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.BgLooper;
import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.plugins.PluginListener;
@@ -80,6 +81,7 @@
private final TunerService mTunerService;
private final PluginManager mPluginManager;
private final DumpController mDumpController;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private final List<Callback> mCallbacks = new ArrayList<>();
private AutoTileManager mAutoTiles;
@@ -99,14 +101,16 @@
PluginManager pluginManager,
TunerService tunerService,
Provider<AutoTileManager> autoTiles,
- DumpController dumpController) {
+ DumpController dumpController,
+ BroadcastDispatcher broadcastDispatcher) {
mIconController = iconController;
mContext = context;
mTunerService = tunerService;
mPluginManager = pluginManager;
mDumpController = dumpController;
+ mBroadcastDispatcher = broadcastDispatcher;
- mServices = new TileServices(this, bgLooper);
+ mServices = new TileServices(this, bgLooper, mBroadcastDispatcher);
defaultFactory.setHost(this);
mQsFactories.add(defaultFactory);
@@ -334,7 +338,8 @@
Intent intent = new Intent().setComponent(component);
TileLifecycleManager lifecycleManager = new TileLifecycleManager(new Handler(),
mContext, mServices, new Tile(), intent,
- new UserHandle(ActivityManager.getCurrentUser()));
+ new UserHandle(ActivityManager.getCurrentUser()),
+ mBroadcastDispatcher);
lifecycleManager.onStopListening();
lifecycleManager.onTileRemoved();
TileLifecycleManager.setTileAdded(mContext, component, false);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
index dcd4633..94a1cf0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
@@ -21,7 +21,6 @@
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
-import android.provider.Settings;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
@@ -36,6 +35,7 @@
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
+import com.android.systemui.util.Utils;
import java.util.ArrayList;
import java.util.Collection;
@@ -72,8 +72,7 @@
removeView((View) mTileLayout);
}
- int flag = Settings.System.getInt(context.getContentResolver(), "qs_media_player", 0);
- if (flag == 1) {
+ if (Utils.useQsMediaPlayer(context)) {
LinearLayout mHorizontalLinearLayout = new LinearLayout(mContext);
mHorizontalLinearLayout.setOrientation(LinearLayout.HORIZONTAL);
mHorizontalLinearLayout.setClipChildren(false);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 592e388..19af235 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -17,6 +17,7 @@
import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
+import static com.android.systemui.util.Utils.useQsMediaPlayer;
import android.annotation.ColorInt;
import android.app.ActivityManager;
@@ -60,6 +61,7 @@
import com.android.systemui.BatteryMeterView;
import com.android.systemui.DualToneHandler;
import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
@@ -69,6 +71,7 @@
import com.android.systemui.privacy.PrivacyItemController;
import com.android.systemui.privacy.PrivacyItemControllerKt;
import com.android.systemui.qs.QSDetail.Callback;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.PhoneStatusBarView;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
@@ -123,6 +126,7 @@
private TouchAnimator mHeaderTextContainerAlphaAnimator;
private TouchAnimator mPrivacyChipAlphaAnimator;
private DualToneHandler mDualToneHandler;
+ private final CommandQueue mCommandQueue;
private View mSystemIconsView;
private View mQuickQsStatusIcons;
@@ -147,6 +151,7 @@
private boolean mPermissionsHubEnabled;
private PrivacyItemController mPrivacyItemController;
+ private BroadcastDispatcher mBroadcastDispatcher;
private final BroadcastReceiver mRingerReceiver = new BroadcastReceiver() {
@Override
@@ -185,7 +190,8 @@
public QuickStatusBarHeader(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
NextAlarmController nextAlarmController, ZenModeController zenModeController,
StatusBarIconController statusBarIconController,
- ActivityStarter activityStarter, PrivacyItemController privacyItemController) {
+ ActivityStarter activityStarter, PrivacyItemController privacyItemController,
+ CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher) {
super(context, attrs);
mAlarmController = nextAlarmController;
mZenController = zenModeController;
@@ -194,6 +200,8 @@
mPrivacyItemController = privacyItemController;
mDualToneHandler = new DualToneHandler(
new ContextThemeWrapper(context, R.style.QSHeaderTheme));
+ mBroadcastDispatcher = broadcastDispatcher;
+ mCommandQueue = commandQueue;
}
@Override
@@ -207,7 +215,7 @@
// Ignore privacy icons because they show in the space above QQS
iconContainer.addIgnoredSlots(getIgnoredIconSlots());
iconContainer.setShouldRestrictIcons(false);
- mIconManager = new TintedIconManager(iconContainer);
+ mIconManager = new TintedIconManager(iconContainer, mCommandQueue);
// Views corresponding to the header info section (e.g. ringer and next alarm).
mHeaderTextContainerView = findViewById(R.id.header_text_container);
@@ -393,11 +401,10 @@
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
- int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0);
if (mQsDisabled) {
lp.height = resources.getDimensionPixelSize(
com.android.internal.R.dimen.quick_qs_offset_height);
- } else if (flag == 1) {
+ } else if (useQsMediaPlayer(mContext)) {
lp.height = Math.max(getMinimumHeight(),
resources.getDimensionPixelSize(
com.android.internal.R.dimen.quick_qs_total_height_with_media));
@@ -547,14 +554,14 @@
if (listening) {
mZenController.addCallback(this);
mAlarmController.addCallback(this);
- mContext.registerReceiver(mRingerReceiver,
+ mBroadcastDispatcher.registerReceiver(mRingerReceiver,
new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
mPrivacyItemController.addCallback(mPICCallback);
} else {
mZenController.removeCallback(this);
mAlarmController.removeCallback(this);
mPrivacyItemController.removeCallback(mPICCallback);
- mContext.unregisterReceiver(mRingerReceiver);
+ mBroadcastDispatcher.unregisterReceiver(mRingerReceiver);
mPrivacyChipLogged = false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
index f59e0c2..9261412 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java
@@ -38,6 +38,8 @@
import androidx.annotation.VisibleForTesting;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+
import java.util.Objects;
import java.util.Set;
@@ -72,6 +74,7 @@
private final UserHandle mUser;
private final IBinder mToken = new Binder();
private final PackageManagerAdapter mPackageManagerAdapter;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private Set<Integer> mQueuedMessages = new ArraySet<>();
private QSTileServiceWrapper mWrapper;
@@ -88,13 +91,15 @@
private boolean mIsBound;
public TileLifecycleManager(Handler handler, Context context, IQSService service, Tile tile,
- Intent intent, UserHandle user) {
- this(handler, context, service, tile, intent, user, new PackageManagerAdapter(context));
+ Intent intent, UserHandle user, BroadcastDispatcher broadcastDispatcher) {
+ this(handler, context, service, tile, intent, user, new PackageManagerAdapter(context),
+ broadcastDispatcher);
}
@VisibleForTesting
TileLifecycleManager(Handler handler, Context context, IQSService service, Tile tile,
- Intent intent, UserHandle user, PackageManagerAdapter packageManagerAdapter) {
+ Intent intent, UserHandle user, PackageManagerAdapter packageManagerAdapter,
+ BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mHandler = handler;
mIntent = intent;
@@ -102,6 +107,7 @@
mIntent.putExtra(TileService.EXTRA_TOKEN, mToken);
mUser = user;
mPackageManagerAdapter = packageManagerAdapter;
+ mBroadcastDispatcher = broadcastDispatcher;
if (DEBUG) Log.d(TAG, "Creating " + mIntent + " " + mUser);
}
@@ -306,13 +312,14 @@
filter.addDataScheme("package");
mContext.registerReceiverAsUser(this, mUser, filter, null, mHandler);
filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
- mContext.registerReceiverAsUser(this, mUser, filter, null, mHandler);
+ mBroadcastDispatcher.registerReceiver(this, filter, mHandler, mUser);
mReceiverRegistered = true;
}
private void stopPackageListening() {
if (DEBUG) Log.d(TAG, "stopPackageListening");
mContext.unregisterReceiver(this);
+ mBroadcastDispatcher.unregisterReceiver(this);
mReceiverRegistered = false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
index 0b4e648..1902d65 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServiceManager.java
@@ -34,6 +34,7 @@
import androidx.annotation.VisibleForTesting;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.qs.external.TileLifecycleManager.TileChangeListener;
import java.util.List;
@@ -72,10 +73,10 @@
private boolean mStarted = false;
TileServiceManager(TileServices tileServices, Handler handler, ComponentName component,
- Tile tile) {
+ Tile tile, BroadcastDispatcher broadcastDispatcher) {
this(tileServices, handler, new TileLifecycleManager(handler,
tileServices.getContext(), tileServices, tile, new Intent().setComponent(component),
- new UserHandle(ActivityManager.getCurrentUser())));
+ new UserHandle(ActivityManager.getCurrentUser()), broadcastDispatcher));
}
@VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
index 13cfa78..db7c6ad 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/external/TileServices.java
@@ -37,6 +37,7 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.Dependency;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -60,13 +61,15 @@
private final Handler mHandler;
private final Handler mMainHandler;
private final QSTileHost mHost;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private int mMaxBound = DEFAULT_MAX_BOUND;
- public TileServices(QSTileHost host, Looper looper) {
+ public TileServices(QSTileHost host, Looper looper, BroadcastDispatcher broadcastDispatcher) {
mHost = host;
mContext = mHost.getContext();
- mContext.registerReceiver(mRequestListeningReceiver,
+ mBroadcastDispatcher = broadcastDispatcher;
+ mBroadcastDispatcher.registerReceiver(mRequestListeningReceiver,
new IntentFilter(TileService.ACTION_REQUEST_LISTENING));
mHandler = new Handler(looper);
mMainHandler = new Handler(Looper.getMainLooper());
@@ -82,7 +85,8 @@
public TileServiceManager getTileWrapper(CustomTile tile) {
ComponentName component = tile.getComponent();
- TileServiceManager service = onCreateTileService(component, tile.getQsTile());
+ TileServiceManager service = onCreateTileService(component, tile.getQsTile(),
+ mBroadcastDispatcher);
synchronized (mServices) {
mServices.put(tile, service);
mTiles.put(component, tile);
@@ -93,8 +97,10 @@
return service;
}
- protected TileServiceManager onCreateTileService(ComponentName component, Tile tile) {
- return new TileServiceManager(this, mHandler, component, tile);
+ protected TileServiceManager onCreateTileService(ComponentName component, Tile tile,
+ BroadcastDispatcher broadcastDispatcher) {
+ return new TileServiceManager(this, mHandler, component, tile,
+ broadcastDispatcher);
}
public void freeService(CustomTile tile, TileServiceManager service) {
@@ -323,7 +329,7 @@
public void destroy() {
synchronized (mServices) {
mServices.values().forEach(service -> service.handleDestroy());
- mContext.unregisterReceiver(mRequestListeningReceiver);
+ mBroadcastDispatcher.unregisterReceiver(mRequestListeningReceiver);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 19e20a9..da74663 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -33,6 +33,7 @@
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyProperties;
import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.GlobalSetting;
@@ -46,13 +47,16 @@
private final Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_airplane);
private final GlobalSetting mSetting;
private final ActivityStarter mActivityStarter;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private boolean mListening;
@Inject
- public AirplaneModeTile(QSHost host, ActivityStarter activityStarter) {
+ public AirplaneModeTile(QSHost host, ActivityStarter activityStarter,
+ BroadcastDispatcher broadcastDispatcher) {
super(host);
mActivityStarter = activityStarter;
+ mBroadcastDispatcher = broadcastDispatcher;
mSetting = new GlobalSetting(mContext, mHandler, Global.AIRPLANE_MODE_ON) {
@Override
@@ -133,9 +137,9 @@
if (listening) {
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- mContext.registerReceiver(mReceiver, filter);
+ mBroadcastDispatcher.registerReceiver(mReceiver, filter);
} else {
- mContext.unregisterReceiver(mReceiver);
+ mBroadcastDispatcher.unregisterReceiver(mReceiver);
}
mSetting.setListening(listening);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 869fa6b..52d1a5b3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -52,6 +52,7 @@
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SysUIToast;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
@@ -78,6 +79,7 @@
private final ZenModeController mController;
private final DndDetailAdapter mDetailAdapter;
private final ActivityStarter mActivityStarter;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private boolean mListening;
private boolean mShowingDetail;
@@ -85,12 +87,13 @@
@Inject
public DndTile(QSHost host, ZenModeController zenModeController,
- ActivityStarter activityStarter) {
+ ActivityStarter activityStarter, BroadcastDispatcher broadcastDispatcher) {
super(host);
mController = zenModeController;
mActivityStarter = activityStarter;
mDetailAdapter = new DndDetailAdapter();
- mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_SET_VISIBLE));
+ mBroadcastDispatcher = broadcastDispatcher;
+ broadcastDispatcher.registerReceiver(mReceiver, new IntentFilter(ACTION_SET_VISIBLE));
mReceiverRegistered = true;
mController.observe(getLifecycle(), mZenCallback);
}
@@ -99,7 +102,7 @@
protected void handleDestroy() {
super.handleDestroy();
if (mReceiverRegistered) {
- mContext.unregisterReceiver(mReceiver);
+ mBroadcastDispatcher.unregisterReceiver(mReceiver);
mReceiverRegistered = false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
index 476a239..8bbfd24 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NfcTile.java
@@ -29,6 +29,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.qs.QSTile.BooleanState;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.tileimpl.QSTileImpl;
@@ -39,12 +40,14 @@
public class NfcTile extends QSTileImpl<BooleanState> {
private NfcAdapter mAdapter;
+ private BroadcastDispatcher mBroadcastDispatcher;
private boolean mListening;
@Inject
- public NfcTile(QSHost host) {
+ public NfcTile(QSHost host, BroadcastDispatcher broadcastDispatcher) {
super(host);
+ mBroadcastDispatcher = broadcastDispatcher;
}
@Override
@@ -56,10 +59,10 @@
public void handleSetListening(boolean listening) {
mListening = listening;
if (mListening) {
- mContext.registerReceiver(mNfcReceiver,
+ mBroadcastDispatcher.registerReceiver(mNfcReceiver,
new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED));
} else {
- mContext.unregisterReceiver(mNfcReceiver);
+ mBroadcastDispatcher.unregisterReceiver(mNfcReceiver);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
index 958695d..60bc6b6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
@@ -20,6 +20,7 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.trust.TrustManager;
import android.content.Context;
@@ -40,23 +41,40 @@
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.phone.StatusBar;
+import java.util.Optional;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+
/**
* An implementation of the Recents interface which proxies to the OverviewProxyService.
*/
+@Singleton
public class OverviewProxyRecentsImpl implements RecentsImplementation {
private final static String TAG = "OverviewProxyRecentsImpl";
+ @Nullable
+ private final Lazy<StatusBar> mStatusBarLazy;
+ private final Optional<Divider> mDividerOptional;
- private SysUiServiceProvider mSysUiServiceProvider;
private Context mContext;
private Handler mHandler;
private TrustManager mTrustManager;
private OverviewProxyService mOverviewProxyService;
+ @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
+ @Inject
+ public OverviewProxyRecentsImpl(Optional<Lazy<StatusBar>> statusBarLazy,
+ Optional<Divider> dividerOptional) {
+ mStatusBarLazy = statusBarLazy.orElse(null);
+ mDividerOptional = dividerOptional;
+ }
+
@Override
public void onStart(Context context, SysUiServiceProvider sysUiServiceProvider) {
mContext = context;
- mSysUiServiceProvider = sysUiServiceProvider;
mHandler = new Handler();
mTrustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
@@ -107,9 +125,8 @@
}
};
// Preload only if device for current user is unlocked
- final StatusBar statusBar = mSysUiServiceProvider.getComponent(StatusBar.class);
- if (statusBar != null && statusBar.isKeyguardShowing()) {
- statusBar.executeRunnableDismissingKeyguard(() -> {
+ if (mStatusBarLazy != null && mStatusBarLazy.get().isKeyguardShowing()) {
+ mStatusBarLazy.get().executeRunnableDismissingKeyguard(() -> {
// Flush trustmanager before checking device locked per user
mTrustManager.reportKeyguardShowingChanged();
mHandler.post(toggleRecents);
@@ -148,10 +165,8 @@
runningTask.id, stackCreateMode, initialBounds)) {
// The overview service is handling split screen, so just skip the wait for the
// first draw and notify the divider to start animating now
- final Divider divider = mSysUiServiceProvider.getComponent(Divider.class);
- if (divider != null) {
- divider.onRecentsDrawn();
- }
+ mDividerOptional.ifPresent(Divider::onRecentsDrawn);
+
return true;
}
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 3fc1398..ba9fc3d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -80,6 +80,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -102,6 +103,7 @@
private final Context mContext;
private final PipUI mPipUI;
+ private final Optional<Divider> mDividerOptional;
private SysUiState mSysUiState;
private final Handler mHandler;
private final NavigationBarController mNavBarController;
@@ -208,10 +210,7 @@
}
long token = Binder.clearCallingIdentity();
try {
- Divider divider = SysUiServiceProvider.getComponent(mContext, Divider.class);
- if (divider != null) {
- divider.onDockedFirstAnimationFrame();
- }
+ mDividerOptional.ifPresent(Divider::onDockedFirstAnimationFrame);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -241,11 +240,9 @@
}
long token = Binder.clearCallingIdentity();
try {
- Divider divider = SysUiServiceProvider.getComponent(mContext, Divider.class);
- if (divider != null) {
- return divider.getView().getNonMinimizedSplitScreenSecondaryBounds();
- }
- return null;
+ return mDividerOptional.map(
+ divider -> divider.getView().getNonMinimizedSplitScreenSecondaryBounds())
+ .orElse(null);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -475,11 +472,12 @@
private final IBinder.DeathRecipient mOverviewServiceDeathRcpt
= this::cleanupAfterDeath;
+ @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
@Inject
public OverviewProxyService(Context context, DeviceProvisionedController provisionController,
NavigationBarController navBarController, NavigationModeController navModeController,
- StatusBarWindowController statusBarWinController,
- SysUiState sysUiState, PipUI pipUI) {
+ StatusBarWindowController statusBarWinController, SysUiState sysUiState, PipUI pipUI,
+ Optional<Divider> dividerOptional) {
mContext = context;
mPipUI = pipUI;
mHandler = new Handler();
@@ -487,6 +485,7 @@
mStatusBarWinController = statusBarWinController;
mDeviceProvisionedController = provisionController;
mConnectionBackoffAttempts = 0;
+ mDividerOptional = dividerOptional;
mRecentsComponentName = ComponentName.unflattenFromString(context.getString(
com.android.internal.R.string.config_recentsComponentName));
mQuickStepIntent = new Intent(ACTION_QUICKSTEP)
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 0a8264b..a8ecc12 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -29,23 +29,27 @@
import java.io.PrintWriter;
import javax.inject.Inject;
+import javax.inject.Singleton;
/**
* A proxy to a Recents implementation.
*/
+@Singleton
public class Recents extends SystemUI implements CommandQueue.Callbacks {
private final RecentsImplementation mImpl;
+ private final CommandQueue mCommandQueue;
@Inject
- public Recents(Context context, RecentsImplementation impl) {
+ public Recents(Context context, RecentsImplementation impl, CommandQueue commandQueue) {
super(context);
mImpl = impl;
+ mCommandQueue = commandQueue;
}
@Override
public void start() {
- getComponent(CommandQueue.class).addCallback(this);
+ mCommandQueue.addCallback(this);
putComponent(Recents.class, this);
mImpl.onStart(mContext, this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
index 3efed3f..8cd17e9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
@@ -23,7 +23,10 @@
import java.io.PrintWriter;
-interface RecentsImplementation {
+/**
+ * API for creating a Recents view.
+ */
+public interface RecentsImplementation {
default void onStart(Context context, SysUiServiceProvider sysUiServiceProvider) {}
default void onBootCompleted() {}
default void onAppTransitionFinished() {}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsModule.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsModule.java
index 5555285..f57bfad 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsModule.java
@@ -19,35 +19,53 @@
import android.content.Context;
import com.android.systemui.R;
+import com.android.systemui.dagger.ContextComponentHelper;
+import dagger.Binds;
import dagger.Module;
import dagger.Provides;
+import dagger.multibindings.ClassKey;
+import dagger.multibindings.IntoMap;
/**
* Dagger injection module for {@link RecentsImplementation}
*/
@Module
-public class RecentsModule {
+public abstract class RecentsModule {
+
/**
* @return The {@link RecentsImplementation} from the config.
*/
@Provides
- public RecentsImplementation provideRecentsImpl(Context context) {
+ public static RecentsImplementation provideRecentsImpl(Context context,
+ ContextComponentHelper componentHelper) {
final String clsName = context.getString(R.string.config_recentsComponent);
if (clsName == null || clsName.length() == 0) {
throw new RuntimeException("No recents component configured", null);
}
- Class<?> cls = null;
- try {
- cls = context.getClassLoader().loadClass(clsName);
- } catch (Throwable t) {
- throw new RuntimeException("Error loading recents component: " + clsName, t);
+ RecentsImplementation impl = componentHelper.resolveRecents(clsName);
+
+ if (impl == null) {
+ Class<?> cls = null;
+ try {
+ cls = context.getClassLoader().loadClass(clsName);
+ } catch (Throwable t) {
+ throw new RuntimeException("Error loading recents component: " + clsName, t);
+ }
+ try {
+ impl = (RecentsImplementation) cls.newInstance();
+ } catch (Throwable t) {
+ throw new RuntimeException("Error creating recents component: " + clsName, t);
+ }
}
- try {
- RecentsImplementation impl = (RecentsImplementation) cls.newInstance();
- return impl;
- } catch (Throwable t) {
- throw new RuntimeException("Error creating recents component: " + clsName, t);
- }
+
+ return impl;
}
+
+ /** */
+ @Binds
+ @IntoMap
+ @ClassKey(OverviewProxyRecentsImpl.class)
+ public abstract RecentsImplementation bindOverviewProxyRecentsImpl(
+ OverviewProxyRecentsImpl impl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 8670d1bd..3ff6d0d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -17,11 +17,11 @@
package com.android.systemui.screenshot;
import static android.content.Context.NOTIFICATION_SERVICE;
+import static android.os.AsyncTask.THREAD_POOL_EXECUTOR;
+import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_ACTION_INTENT;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_CANCEL_NOTIFICATION;
-import static com.android.systemui.screenshot.GlobalScreenshot.EXTRA_DISALLOW_ENTER_PIP;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_CORNER_FLOW;
import static com.android.systemui.statusbar.phone.StatusBar.SYSTEM_DIALOG_REASON_SCREENSHOT;
import android.animation.Animator;
@@ -29,7 +29,10 @@
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.ActivityOptions;
+import android.app.ActivityTaskManager;
import android.app.Notification;
import android.app.Notification.BigPictureStyle;
import android.app.NotificationManager;
@@ -42,6 +45,7 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -59,12 +63,20 @@
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
import android.os.PowerManager;
import android.os.Process;
+import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.DeviceConfig;
import android.provider.MediaStore;
import android.text.TextUtils;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.util.Slog;
import android.view.Display;
import android.view.LayoutInflater;
@@ -77,10 +89,13 @@
import android.widget.ImageView;
import android.widget.Toast;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.R;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.SystemUI;
+import com.android.systemui.SystemUIFactory;
+import com.android.systemui.dagger.qualifiers.MainResources;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.util.NotificationChannels;
@@ -92,367 +107,436 @@
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
+import java.util.Collections;
import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.function.Function;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import dagger.Lazy;
/**
- * POD used in the AsyncTask which saves an image in the background.
+ * Class for handling device screen shots
*/
-class SaveImageInBackgroundData {
- Context context;
- Bitmap image;
- Uri imageUri;
- Runnable finisher;
- int iconSize;
- int previewWidth;
- int previewheight;
- int errorMsgResId;
+@Singleton
+public class GlobalScreenshot {
- void clearImage() {
- image = null;
- imageUri = null;
- iconSize = 0;
- }
- void clearContext() {
- context = null;
- }
-}
+ /**
+ * POD used in the AsyncTask which saves an image in the background.
+ */
+ private static class SaveImageInBackgroundData {
+ public Context context;
+ public Bitmap image;
+ public Uri imageUri;
+ public Runnable finisher;
+ public Function<PendingIntent, Void> onEditReady;
+ public int iconSize;
+ public int previewWidth;
+ public int previewheight;
+ public int errorMsgResId;
-/**
- * An AsyncTask that saves an image to the media store in the background.
- */
-class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
- private static final String TAG = "SaveImageInBackgroundTask";
-
- private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
- private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
-
- private final SaveImageInBackgroundData mParams;
- private final NotificationManager mNotificationManager;
- private final Notification.Builder mNotificationBuilder, mPublicNotificationBuilder;
- private final String mImageFileName;
- private final long mImageTime;
- private final BigPictureStyle mNotificationStyle;
- private final int mImageWidth;
- private final int mImageHeight;
-
- SaveImageInBackgroundTask(Context context, SaveImageInBackgroundData data,
- NotificationManager nManager) {
- Resources r = context.getResources();
-
- // Prepare all the output metadata
- mParams = data;
- mImageTime = System.currentTimeMillis();
- String imageDate = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(mImageTime));
- mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate);
-
- // Create the large notification icon
- mImageWidth = data.image.getWidth();
- mImageHeight = data.image.getHeight();
- int iconSize = data.iconSize;
- int previewWidth = data.previewWidth;
- int previewHeight = data.previewheight;
-
- Paint paint = new Paint();
- ColorMatrix desat = new ColorMatrix();
- desat.setSaturation(0.25f);
- paint.setColorFilter(new ColorMatrixColorFilter(desat));
- Matrix matrix = new Matrix();
- int overlayColor = 0x40FFFFFF;
-
- matrix.setTranslate((previewWidth - mImageWidth) / 2, (previewHeight - mImageHeight) / 2);
- Bitmap picture = generateAdjustedHwBitmap(data.image, previewWidth, previewHeight, matrix,
- paint, overlayColor);
-
- // Note, we can't use the preview for the small icon, since it is non-square
- float scale = (float) iconSize / Math.min(mImageWidth, mImageHeight);
- matrix.setScale(scale, scale);
- matrix.postTranslate((iconSize - (scale * mImageWidth)) / 2,
- (iconSize - (scale * mImageHeight)) / 2);
- Bitmap icon = generateAdjustedHwBitmap(data.image, iconSize, iconSize, matrix, paint,
- overlayColor);
-
- mNotificationManager = nManager;
- final long now = System.currentTimeMillis();
-
- // Setup the notification
- mNotificationStyle = new Notification.BigPictureStyle()
- .bigPicture(picture.createAshmemBitmap());
-
- // The public notification will show similar info but with the actual screenshot omitted
- mPublicNotificationBuilder =
- new Notification.Builder(context, NotificationChannels.SCREENSHOTS_HEADSUP)
- .setContentTitle(r.getString(R.string.screenshot_saving_title))
- .setSmallIcon(R.drawable.stat_notify_image)
- .setCategory(Notification.CATEGORY_PROGRESS)
- .setWhen(now)
- .setShowWhen(true)
- .setColor(r.getColor(
- com.android.internal.R.color.system_notification_accent_color));
- SystemUI.overrideNotificationAppName(context, mPublicNotificationBuilder, true);
-
- mNotificationBuilder = new Notification.Builder(context,
- NotificationChannels.SCREENSHOTS_HEADSUP)
- .setContentTitle(r.getString(R.string.screenshot_saving_title))
- .setSmallIcon(R.drawable.stat_notify_image)
- .setWhen(now)
- .setShowWhen(true)
- .setColor(r.getColor(com.android.internal.R.color.system_notification_accent_color))
- .setStyle(mNotificationStyle)
- .setPublicVersion(mPublicNotificationBuilder.build());
- mNotificationBuilder.setFlag(Notification.FLAG_NO_CLEAR, true);
- SystemUI.overrideNotificationAppName(context, mNotificationBuilder, true);
-
- mNotificationManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT,
- mNotificationBuilder.build());
-
- /**
- * NOTE: The following code prepares the notification builder for updating the notification
- * after the screenshot has been written to disk.
- */
-
- // On the tablet, the large icon makes the notification appear as if it is clickable (and
- // on small devices, the large icon is not shown) so defer showing the large icon until
- // we compose the final post-save notification below.
- mNotificationBuilder.setLargeIcon(icon.createAshmemBitmap());
- // But we still don't set it for the expanded view, allowing the smallIcon to show here.
- mNotificationStyle.bigLargeIcon((Bitmap) null);
+ void clearImage() {
+ image = null;
+ imageUri = null;
+ iconSize = 0;
+ }
+ void clearContext() {
+ context = null;
+ }
}
/**
- * Generates a new hardware bitmap with specified values, copying the content from the passed
- * in bitmap.
+ * An AsyncTask that saves an image to the media store in the background.
*/
- private Bitmap generateAdjustedHwBitmap(Bitmap bitmap, int width, int height, Matrix matrix,
- Paint paint, int color) {
- Picture picture = new Picture();
- Canvas canvas = picture.beginRecording(width, height);
- canvas.drawColor(color);
- canvas.drawBitmap(bitmap, matrix, paint);
- picture.endRecording();
- return Bitmap.createBitmap(picture);
- }
+ private static class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
+ private static final String TAG = "SaveImageInBackgroundTask";
- @Override
- protected Void doInBackground(Void... paramsUnused) {
- if (isCancelled()) {
- return null;
- }
+ private static final String SCREENSHOT_FILE_NAME_TEMPLATE = "Screenshot_%s.png";
+ private static final String SCREENSHOT_SHARE_SUBJECT_TEMPLATE = "Screenshot (%s)";
- // By default, AsyncTask sets the worker thread to have background thread priority, so bump
- // it back up so that we save a little quicker.
- Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
+ private final SaveImageInBackgroundData mParams;
+ private final NotificationManager mNotificationManager;
+ private final Notification.Builder mNotificationBuilder, mPublicNotificationBuilder;
+ private final String mImageFileName;
+ private final long mImageTime;
+ private final BigPictureStyle mNotificationStyle;
+ private final int mImageWidth;
+ private final int mImageHeight;
+ private final Handler mHandler;
+ private final ScreenshotNotificationSmartActionsProvider mSmartActionsProvider;
- Context context = mParams.context;
- Bitmap image = mParams.image;
- Resources r = context.getResources();
-
- try {
- // Save the screenshot to the MediaStore
- final MediaStore.PendingParams params = new MediaStore.PendingParams(
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mImageFileName, "image/png");
- params.setRelativePath(Environment.DIRECTORY_PICTURES + File.separator
- + Environment.DIRECTORY_SCREENSHOTS);
-
- final Uri uri = MediaStore.createPending(context, params);
- final MediaStore.PendingSession session = MediaStore.openPending(context, uri);
- try {
- try (OutputStream out = session.openOutputStream()) {
- if (!image.compress(Bitmap.CompressFormat.PNG, 100, out)) {
- throw new IOException("Failed to compress");
- }
- }
- session.publish();
- } catch (Exception e) {
- session.abandon();
- throw e;
- } finally {
- IoUtils.closeQuietly(session);
- }
-
- // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
- // order to do some common work like dismissing the keyguard and sending
- // closeSystemWindows
-
- // Create a share intent, this will always go through the chooser activity first which
- // should not trigger auto-enter PiP
- String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
- String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
- Intent sharingIntent = new Intent(Intent.ACTION_SEND);
- sharingIntent.setType("image/png");
- sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
- // Include URI in ClipData also, so that grantPermission picks it up.
- // We don't use setData here because some apps interpret this as "to:".
- ClipData clipdata = new ClipData(new ClipDescription("content",
- new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
- new ClipData.Item(uri));
- sharingIntent.setClipData(clipdata);
- sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
- sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- // Make sure pending intents for the system user are still unique across users
- // by setting the (otherwise unused) request code to the current user id.
- int requestCode = context.getUserId();
-
- PendingIntent chooserAction = PendingIntent.getBroadcast(context, requestCode,
- new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
- PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
- Intent sharingChooserIntent = Intent.createChooser(sharingIntent, null,
- chooserAction.getIntentSender())
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
- .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- // Create a share action for the notification
- PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
- new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
- .putExtra(EXTRA_ACTION_INTENT, sharingChooserIntent)
- .putExtra(EXTRA_DISALLOW_ENTER_PIP, true)
- .setAction(Intent.ACTION_SEND),
- PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
- Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
- R.drawable.ic_screenshot_share,
- r.getString(com.android.internal.R.string.share), shareAction);
- mNotificationBuilder.addAction(shareActionBuilder.build());
-
- // Create an edit intent, if a specific package is provided as the editor, then launch
- // that directly
- String editorPackage = context.getString(R.string.config_screenshotEditor);
- Intent editIntent = new Intent(Intent.ACTION_EDIT);
- if (!TextUtils.isEmpty(editorPackage)) {
- editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
- }
- editIntent.setType("image/png");
- editIntent.setData(uri);
- editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-
- // Create a edit action
- PendingIntent editAction = PendingIntent.getBroadcastAsUser(context, requestCode,
- new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
- .putExtra(EXTRA_ACTION_INTENT, editIntent)
- .putExtra(EXTRA_CANCEL_NOTIFICATION, editIntent.getComponent() != null)
- .setAction(Intent.ACTION_EDIT),
- PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
- Notification.Action.Builder editActionBuilder = new Notification.Action.Builder(
- R.drawable.ic_screenshot_edit,
- r.getString(com.android.internal.R.string.screenshot_edit), editAction);
- mNotificationBuilder.addAction(editActionBuilder.build());
-
- // Create a delete action for the notification
- PendingIntent deleteAction = PendingIntent.getBroadcast(context, requestCode,
- new Intent(context, GlobalScreenshot.DeleteScreenshotReceiver.class)
- .putExtra(GlobalScreenshot.SCREENSHOT_URI_ID, uri.toString()),
- PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
- Notification.Action.Builder deleteActionBuilder = new Notification.Action.Builder(
- R.drawable.ic_screenshot_delete,
- r.getString(com.android.internal.R.string.delete), deleteAction);
- mNotificationBuilder.addAction(deleteActionBuilder.build());
-
- mParams.imageUri = uri;
- mParams.image = null;
- mParams.errorMsgResId = 0;
- } catch (Exception e) {
- // IOException/UnsupportedOperationException may be thrown if external storage is not
- // mounted
- Slog.e(TAG, "unable to save screenshot", e);
- mParams.clearImage();
- mParams.errorMsgResId = R.string.screenshot_failed_to_save_text;
- }
-
- // Recycle the bitmap data
- if (image != null) {
- image.recycle();
- }
-
- return null;
- }
-
- @Override
- protected void onPostExecute(Void params) {
- if (mParams.errorMsgResId != 0) {
- // Show a message that we've failed to save the image to disk
- GlobalScreenshot.notifyScreenshotError(mParams.context, mNotificationManager,
- mParams.errorMsgResId);
- } else {
- // Show the final notification to indicate screenshot saved
- Context context = mParams.context;
+ SaveImageInBackgroundTask(Context context, SaveImageInBackgroundData data,
+ NotificationManager nManager) {
Resources r = context.getResources();
- // Create the intent to show the screenshot in gallery
- Intent launchIntent = new Intent(Intent.ACTION_VIEW);
- launchIntent.setDataAndType(mParams.imageUri, "image/png");
- launchIntent.setFlags(
- Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ // Prepare all the output metadata
+ mParams = data;
+ mImageTime = System.currentTimeMillis();
+ String imageDate = new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(mImageTime));
+ mImageFileName = String.format(SCREENSHOT_FILE_NAME_TEMPLATE, imageDate);
+ // Initialize screenshot notification smart actions provider.
+ mHandler = new Handler();
+ mSmartActionsProvider =
+ SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider();
+
+ // Create the large notification icon
+ mImageWidth = data.image.getWidth();
+ mImageHeight = data.image.getHeight();
+ int iconSize = data.iconSize;
+ int previewWidth = data.previewWidth;
+ int previewHeight = data.previewheight;
+
+ Paint paint = new Paint();
+ ColorMatrix desat = new ColorMatrix();
+ desat.setSaturation(0.25f);
+ paint.setColorFilter(new ColorMatrixColorFilter(desat));
+ Matrix matrix = new Matrix();
+ int overlayColor = 0x40FFFFFF;
+
+ matrix.setTranslate((previewWidth - mImageWidth) / 2,
+ (previewHeight - mImageHeight) / 2);
+ Bitmap picture = generateAdjustedHwBitmap(data.image, previewWidth, previewHeight,
+ matrix, paint, overlayColor);
+
+ // Note, we can't use the preview for the small icon, since it is non-square
+ float scale = (float) iconSize / Math.min(mImageWidth, mImageHeight);
+ matrix.setScale(scale, scale);
+ matrix.postTranslate((iconSize - (scale * mImageWidth)) / 2,
+ (iconSize - (scale * mImageHeight)) / 2);
+ Bitmap icon = generateAdjustedHwBitmap(data.image, iconSize, iconSize, matrix, paint,
+ overlayColor);
+
+ mNotificationManager = nManager;
final long now = System.currentTimeMillis();
- // Update the text and the icon for the existing notification
- mPublicNotificationBuilder
- .setContentTitle(r.getString(R.string.screenshot_saved_title))
- .setContentText(r.getString(R.string.screenshot_saved_text))
- .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
+ // Setup the notification
+ mNotificationStyle = new Notification.BigPictureStyle()
+ .bigPicture(picture.createAshmemBitmap());
+
+ // The public notification will show similar info but with the actual screenshot omitted
+ mPublicNotificationBuilder =
+ new Notification.Builder(context, NotificationChannels.SCREENSHOTS_HEADSUP)
+ .setContentTitle(r.getString(R.string.screenshot_saving_title))
+ .setSmallIcon(R.drawable.stat_notify_image)
+ .setCategory(Notification.CATEGORY_PROGRESS)
+ .setWhen(now)
+ .setShowWhen(true)
+ .setColor(r.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
+ SystemUI.overrideNotificationAppName(context, mPublicNotificationBuilder, true);
+
+ mNotificationBuilder = new Notification.Builder(context,
+ NotificationChannels.SCREENSHOTS_HEADSUP)
+ .setContentTitle(r.getString(R.string.screenshot_saving_title))
+ .setSmallIcon(R.drawable.stat_notify_image)
.setWhen(now)
- .setAutoCancel(true)
- .setColor(context.getColor(
- com.android.internal.R.color.system_notification_accent_color));
- mNotificationBuilder
- .setContentTitle(r.getString(R.string.screenshot_saved_title))
- .setContentText(r.getString(R.string.screenshot_saved_text))
- .setContentIntent(PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
- .setWhen(now)
- .setAutoCancel(true)
- .setColor(context.getColor(
- com.android.internal.R.color.system_notification_accent_color))
- .setPublicVersion(mPublicNotificationBuilder.build())
- .setFlag(Notification.FLAG_NO_CLEAR, false);
+ .setShowWhen(true)
+ .setColor(r.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setStyle(mNotificationStyle)
+ .setPublicVersion(mPublicNotificationBuilder.build());
+ mNotificationBuilder.setFlag(Notification.FLAG_NO_CLEAR, true);
+ SystemUI.overrideNotificationAppName(context, mNotificationBuilder, true);
mNotificationManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT,
mNotificationBuilder.build());
+
+ /**
+ * NOTE: The following code prepares the notification builder for updating the
+ * notification after the screenshot has been written to disk.
+ */
+
+ // On the tablet, the large icon makes the notification appear as if it is clickable
+ // (and on small devices, the large icon is not shown) so defer showing the large icon
+ // until we compose the final post-save notification below.
+ mNotificationBuilder.setLargeIcon(icon.createAshmemBitmap());
+ // But we still don't set it for the expanded view, allowing the smallIcon to show here.
+ mNotificationStyle.bigLargeIcon((Bitmap) null);
}
- mParams.finisher.run();
- mParams.clearContext();
+
+ private int getUserHandleOfForegroundApplication(Context context) {
+ // This logic matches
+ // com.android.systemui.statusbar.phone.PhoneStatusBarPolicy#updateManagedProfile
+ try {
+ return ActivityTaskManager.getService().getLastResumedActivityUserId();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "getUserHandleOfForegroundApplication: ", e);
+ return context.getUserId();
+ }
+ }
+
+ private boolean isManagedProfile(Context context) {
+ UserManager manager = UserManager.get(context);
+ UserInfo info = manager.getUserInfo(getUserHandleOfForegroundApplication(context));
+ return info.isManagedProfile();
+ }
+
+ /**
+ * Generates a new hardware bitmap with specified values, copying the content from the
+ * passed in bitmap.
+ */
+ private Bitmap generateAdjustedHwBitmap(Bitmap bitmap, int width, int height, Matrix matrix,
+ Paint paint, int color) {
+ Picture picture = new Picture();
+ Canvas canvas = picture.beginRecording(width, height);
+ canvas.drawColor(color);
+ canvas.drawBitmap(bitmap, matrix, paint);
+ picture.endRecording();
+ return Bitmap.createBitmap(picture);
+ }
+
+ @Override
+ protected Void doInBackground(Void... paramsUnused) {
+ if (isCancelled()) {
+ return null;
+ }
+
+ // By default, AsyncTask sets the worker thread to have background thread priority,
+ // so bump it back up so that we save a little quicker.
+ Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);
+
+ Context context = mParams.context;
+ Bitmap image = mParams.image;
+ boolean smartActionsEnabled = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.ENABLE_SCREENSHOT_NOTIFICATION_SMART_ACTIONS, true);
+ CompletableFuture<List<Notification.Action>> smartActionsFuture = getSmartActionsFuture(
+ context, image, mSmartActionsProvider, mHandler, smartActionsEnabled,
+ isManagedProfile(context));
+
+ Resources r = context.getResources();
+
+ try {
+ // Save the screenshot to the MediaStore
+ final MediaStore.PendingParams params = new MediaStore.PendingParams(
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI, mImageFileName, "image/png");
+ params.setRelativePath(Environment.DIRECTORY_PICTURES + File.separator
+ + Environment.DIRECTORY_SCREENSHOTS);
+
+ final Uri uri = MediaStore.createPending(context, params);
+ final MediaStore.PendingSession session = MediaStore.openPending(context, uri);
+ try {
+ try (OutputStream out = session.openOutputStream()) {
+ if (!image.compress(Bitmap.CompressFormat.PNG, 100, out)) {
+ throw new IOException("Failed to compress");
+ }
+ }
+ session.publish();
+ } catch (Exception e) {
+ session.abandon();
+ throw e;
+ } finally {
+ IoUtils.closeQuietly(session);
+ }
+
+ // Note: Both the share and edit actions are proxied through ActionProxyReceiver in
+ // order to do some common work like dismissing the keyguard and sending
+ // closeSystemWindows
+
+ // Create a share intent, this will always go through the chooser activity first
+ // which should not trigger auto-enter PiP
+ String subjectDate = DateFormat.getDateTimeInstance().format(new Date(mImageTime));
+ String subject = String.format(SCREENSHOT_SHARE_SUBJECT_TEMPLATE, subjectDate);
+ Intent sharingIntent = new Intent(Intent.ACTION_SEND);
+ sharingIntent.setType("image/png");
+ sharingIntent.putExtra(Intent.EXTRA_STREAM, uri);
+ // Include URI in ClipData also, so that grantPermission picks it up.
+ // We don't use setData here because some apps interpret this as "to:".
+ ClipData clipdata = new ClipData(new ClipDescription("content",
+ new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
+ new ClipData.Item(uri));
+ sharingIntent.setClipData(clipdata);
+ sharingIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
+ sharingIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ // Make sure pending intents for the system user are still unique across users
+ // by setting the (otherwise unused) request code to the current user id.
+ int requestCode = context.getUserId();
+
+ PendingIntent chooserAction = PendingIntent.getBroadcast(context, requestCode,
+ new Intent(context, GlobalScreenshot.TargetChosenReceiver.class),
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
+ Intent sharingChooserIntent = Intent.createChooser(sharingIntent, null,
+ chooserAction.getIntentSender())
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ // Create a share action for the notification
+ PendingIntent shareAction = PendingIntent.getBroadcastAsUser(context, requestCode,
+ new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
+ .putExtra(EXTRA_ACTION_INTENT, sharingChooserIntent)
+ .putExtra(EXTRA_DISALLOW_ENTER_PIP, true)
+ .setAction(Intent.ACTION_SEND),
+ PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
+ Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
+ R.drawable.ic_screenshot_share,
+ r.getString(com.android.internal.R.string.share), shareAction);
+ mNotificationBuilder.addAction(shareActionBuilder.build());
+
+ // Create an edit intent, if a specific package is provided as the editor, then
+ // launch that directly
+ String editorPackage = context.getString(R.string.config_screenshotEditor);
+ Intent editIntent = new Intent(Intent.ACTION_EDIT);
+ if (!TextUtils.isEmpty(editorPackage)) {
+ editIntent.setComponent(ComponentName.unflattenFromString(editorPackage));
+ }
+ editIntent.setType("image/png");
+ editIntent.setData(uri);
+ editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ editIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+ // Create a edit action
+ PendingIntent editAction = PendingIntent.getBroadcastAsUser(context, requestCode,
+ new Intent(context, GlobalScreenshot.ActionProxyReceiver.class)
+ .putExtra(EXTRA_ACTION_INTENT, editIntent)
+ .putExtra(EXTRA_CANCEL_NOTIFICATION,
+ editIntent.getComponent() != null)
+ .setAction(Intent.ACTION_EDIT),
+ PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
+ Notification.Action.Builder editActionBuilder = new Notification.Action.Builder(
+ R.drawable.ic_screenshot_edit,
+ r.getString(com.android.internal.R.string.screenshot_edit), editAction);
+ mNotificationBuilder.addAction(editActionBuilder.build());
+ if (editAction != null && mParams.onEditReady != null) {
+ mParams.onEditReady.apply(editAction);
+ }
+
+ // Create a delete action for the notification
+ PendingIntent deleteAction = PendingIntent.getBroadcast(context, requestCode,
+ new Intent(context, GlobalScreenshot.DeleteScreenshotReceiver.class)
+ .putExtra(GlobalScreenshot.SCREENSHOT_URI_ID, uri.toString()),
+ PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
+ Notification.Action.Builder deleteActionBuilder = new Notification.Action.Builder(
+ R.drawable.ic_screenshot_delete,
+ r.getString(com.android.internal.R.string.delete), deleteAction);
+ mNotificationBuilder.addAction(deleteActionBuilder.build());
+
+ mParams.imageUri = uri;
+ mParams.image = null;
+ mParams.errorMsgResId = 0;
+
+ if (smartActionsEnabled) {
+ int timeoutMs = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags
+ .SCREENSHOT_NOTIFICATION_SMART_ACTIONS_TIMEOUT_MS,
+ 1000);
+ List<Notification.Action> smartActions = getSmartActions(smartActionsFuture,
+ timeoutMs);
+ for (Notification.Action action : smartActions) {
+ mNotificationBuilder.addAction(action);
+ }
+ }
+ } catch (Exception e) {
+ // IOException/UnsupportedOperationException may be thrown if external storage is
+ // not mounted
+ Slog.e(TAG, "unable to save screenshot", e);
+ mParams.clearImage();
+ mParams.errorMsgResId = R.string.screenshot_failed_to_save_text;
+ }
+
+ // Recycle the bitmap data
+ if (image != null) {
+ image.recycle();
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void params) {
+ if (mParams.errorMsgResId != 0) {
+ // Show a message that we've failed to save the image to disk
+ GlobalScreenshot.notifyScreenshotError(mParams.context, mNotificationManager,
+ mParams.errorMsgResId);
+ } else {
+ if (mParams.onEditReady != null) {
+ // Cancel the "saving screenshot" notification
+ mNotificationManager.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
+ } else {
+ // Show the final notification to indicate screenshot saved
+ Context context = mParams.context;
+ Resources r = context.getResources();
+
+ // Create the intent to show the screenshot in gallery
+ Intent launchIntent = new Intent(Intent.ACTION_VIEW);
+ launchIntent.setDataAndType(mParams.imageUri, "image/png");
+ launchIntent.setFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ final long now = System.currentTimeMillis();
+
+ // Update the text and the icon for the existing notification
+ mPublicNotificationBuilder
+ .setContentTitle(r.getString(R.string.screenshot_saved_title))
+ .setContentText(r.getString(R.string.screenshot_saved_text))
+ .setContentIntent(
+ PendingIntent.getActivity(mParams.context, 0, launchIntent, 0))
+ .setWhen(now)
+ .setAutoCancel(true)
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color));
+ mNotificationBuilder
+ .setContentTitle(r.getString(R.string.screenshot_saved_title))
+ .setContentText(r.getString(R.string.screenshot_saved_text))
+ .setContentIntent(PendingIntent.getActivity(mParams.context, 0,
+ launchIntent, 0))
+ .setWhen(now)
+ .setAutoCancel(true)
+ .setColor(context.getColor(
+ com.android.internal.R.color.system_notification_accent_color))
+ .setPublicVersion(mPublicNotificationBuilder.build())
+ .setFlag(Notification.FLAG_NO_CLEAR, false);
+
+ mNotificationManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT,
+ mNotificationBuilder.build());
+ }
+ }
+ mParams.finisher.run();
+ mParams.clearContext();
+ }
+
+ @Override
+ protected void onCancelled(Void params) {
+ // If we are cancelled while the task is running in the background, we may get null
+ // params. The finisher is expected to always be called back, so just use the baked-in
+ // params from the ctor in any case.
+ mParams.finisher.run();
+ mParams.clearImage();
+ mParams.clearContext();
+
+ // Cancel the posted notification
+ mNotificationManager.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
+ }
}
- @Override
- protected void onCancelled(Void params) {
- // If we are cancelled while the task is running in the background, we may get null params.
- // The finisher is expected to always be called back, so just use the baked-in params from
- // the ctor in any case.
- mParams.finisher.run();
- mParams.clearImage();
- mParams.clearContext();
+ /**
+ * An AsyncTask that deletes an image from the media store in the background.
+ */
+ private static class DeleteImageInBackgroundTask extends AsyncTask<Uri, Void, Void> {
+ private Context mContext;
- // Cancel the posted notification
- mNotificationManager.cancel(SystemMessage.NOTE_GLOBAL_SCREENSHOT);
- }
-}
+ DeleteImageInBackgroundTask(Context context) {
+ mContext = context;
+ }
-/**
- * An AsyncTask that deletes an image from the media store in the background.
- */
-class DeleteImageInBackgroundTask extends AsyncTask<Uri, Void, Void> {
- private Context mContext;
+ @Override
+ protected Void doInBackground(Uri... params) {
+ if (params.length != 1) return null;
- DeleteImageInBackgroundTask(Context context) {
- mContext = context;
+ Uri screenshotUri = params[0];
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.delete(screenshotUri, null, null);
+ return null;
+ }
}
- @Override
- protected Void doInBackground(Uri... params) {
- if (params.length != 1) return null;
-
- Uri screenshotUri = params[0];
- ContentResolver resolver = mContext.getContentResolver();
- resolver.delete(screenshotUri, null, null);
- return null;
- }
-}
-
-class GlobalScreenshot {
static final String SCREENSHOT_URI_ID = "android:screenshot_uri_id";
static final String EXTRA_ACTION_INTENT = "android:screenshot_action_intent";
static final String EXTRA_CANCEL_NOTIFICATION = "android:screenshot_cancel_notification";
@@ -470,8 +554,12 @@
private static final float SCREENSHOT_SCALE = 1f;
private static final float SCREENSHOT_DROP_IN_MIN_SCALE = SCREENSHOT_SCALE * 0.725f;
private static final float SCREENSHOT_DROP_OUT_MIN_SCALE = SCREENSHOT_SCALE * 0.45f;
+ private static final float SCREENSHOT_CORNER_MIN_SCALE = SCREENSHOT_SCALE * 0.2f;
private static final float SCREENSHOT_FAST_DROP_OUT_MIN_SCALE = SCREENSHOT_SCALE * 0.6f;
private static final float SCREENSHOT_DROP_OUT_MIN_SCALE_OFFSET = 0f;
+ private static final float SCREENSHOT_CORNER_MIN_SCALE_OFFSET = .1f;
+ private static final long SCREENSHOT_CORNER_TIMEOUT_MILLIS = 8000;
+ private static final int MESSAGE_CORNER_TIMEOUT = 2;
private final int mPreviewWidth;
private final int mPreviewHeight;
@@ -499,23 +587,34 @@
private MediaActionSound mCameraSound;
+ private final Handler mScreenshotHandler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MESSAGE_CORNER_TIMEOUT:
+ GlobalScreenshot.this.clearScreenshot();
+ break;
+ default:
+ break;
+ }
+ }
+ };
+
/**
* @param context everything needs a context :(
*/
- public GlobalScreenshot(Context context) {
- Resources r = context.getResources();
+ @Inject
+ public GlobalScreenshot(Context context, @MainResources Resources resources,
+ LayoutInflater layoutInflater) {
mContext = context;
- LayoutInflater layoutInflater = (LayoutInflater)
- context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Inflate the screenshot layout
mScreenshotLayout = layoutInflater.inflate(R.layout.global_screenshot, null);
- mBackgroundView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_background);
- mScreenshotView = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot);
- mScreenshotFlash = (ImageView) mScreenshotLayout.findViewById(R.id.global_screenshot_flash);
- mScreenshotSelectorView = (ScreenshotSelectorView) mScreenshotLayout.findViewById(
- R.id.global_screenshot_selector);
+ mBackgroundView = mScreenshotLayout.findViewById(R.id.global_screenshot_background);
+ mScreenshotView = mScreenshotLayout.findViewById(R.id.global_screenshot);
+ mScreenshotFlash = mScreenshotLayout.findViewById(R.id.global_screenshot_flash);
+ mScreenshotSelectorView = mScreenshotLayout.findViewById(R.id.global_screenshot_selector);
mScreenshotLayout.setFocusable(true);
mScreenshotSelectorView.setFocusable(true);
mScreenshotSelectorView.setFocusableInTouchMode(true);
@@ -546,16 +645,16 @@
// Get the various target sizes
mNotificationIconSize =
- r.getDimensionPixelSize(android.R.dimen.notification_large_icon_height);
+ resources.getDimensionPixelSize(android.R.dimen.notification_large_icon_height);
// Scale has to account for both sides of the bg
- mBgPadding = (float) r.getDimensionPixelSize(R.dimen.global_screenshot_bg_padding);
+ mBgPadding = (float) resources.getDimensionPixelSize(R.dimen.global_screenshot_bg_padding);
mBgPaddingScale = mBgPadding / mDisplayMetrics.widthPixels;
// determine the optimal preview size
int panelWidth = 0;
try {
- panelWidth = r.getDimensionPixelSize(R.dimen.notification_panel_width);
+ panelWidth = resources.getDimensionPixelSize(R.dimen.notification_panel_width);
} catch (Resources.NotFoundException e) {
}
if (panelWidth <= 0) {
@@ -563,7 +662,7 @@
panelWidth = mDisplayMetrics.widthPixels;
}
mPreviewWidth = panelWidth;
- mPreviewHeight = r.getDimensionPixelSize(R.dimen.notification_max_height);
+ mPreviewHeight = resources.getDimensionPixelSize(R.dimen.notification_max_height);
// Setup the Camera shutter sound
mCameraSound = new MediaActionSound();
@@ -573,12 +672,14 @@
/**
* Creates a new worker thread and saves the screenshot to the media store.
*/
- private void saveScreenshotInWorkerThread(Runnable finisher) {
+ private void saveScreenshotInWorkerThread(
+ Runnable finisher, @Nullable Function<PendingIntent, Void> onEditReady) {
SaveImageInBackgroundData data = new SaveImageInBackgroundData();
data.context = mContext;
data.image = mScreenBitmap;
data.iconSize = mNotificationIconSize;
data.finisher = finisher;
+ data.onEditReady = onEditReady;
data.previewWidth = mPreviewWidth;
data.previewheight = mPreviewHeight;
if (mSaveInBgTask != null) {
@@ -588,6 +689,10 @@
.execute();
}
+ private void saveScreenshotInWorkerThread(Runnable finisher) {
+ saveScreenshotInWorkerThread(finisher, null);
+ }
+
/**
* Takes a screenshot of the current display and shows an animation.
*/
@@ -682,6 +787,22 @@
}
/**
+ * Clears current screenshot
+ */
+ private void clearScreenshot() {
+ if (mScreenshotLayout.isAttachedToWindow()) {
+ mWindowManager.removeView(mScreenshotLayout);
+ }
+
+ // Clear any references to the bitmap
+ mScreenBitmap = null;
+ mScreenshotView.setImageBitmap(null);
+ mBackgroundView.setVisibility(View.GONE);
+ mScreenshotView.setVisibility(View.GONE);
+ mScreenshotView.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+
+ /**
* Starts the animation after taking the screenshot
*/
private void startAnimation(final Runnable finisher, int w, int h, boolean statusBarVisible,
@@ -705,34 +826,55 @@
mScreenshotAnimation.removeAllListeners();
}
+ boolean useCornerFlow =
+ DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI, SCREENSHOT_CORNER_FLOW, false);
mWindowManager.addView(mScreenshotLayout, mWindowLayoutParams);
ValueAnimator screenshotDropInAnim = createScreenshotDropInAnimation();
- ValueAnimator screenshotFadeOutAnim = createScreenshotDropOutAnimation(w, h,
- statusBarVisible, navBarVisible);
+ ValueAnimator screenshotFadeOutAnim = useCornerFlow
+ ? createScreenshotToCornerAnimation(w, h)
+ : createScreenshotDropOutAnimation(w, h, statusBarVisible, navBarVisible);
mScreenshotAnimation = new AnimatorSet();
mScreenshotAnimation.playSequentially(screenshotDropInAnim, screenshotFadeOutAnim);
mScreenshotAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// Save the screenshot once we have a bit of time now
- saveScreenshotInWorkerThread(finisher);
- mWindowManager.removeView(mScreenshotLayout);
-
- // Clear any references to the bitmap
- mScreenBitmap = null;
- mScreenshotView.setImageBitmap(null);
+ if (!useCornerFlow) {
+ saveScreenshotInWorkerThread(finisher);
+ clearScreenshot();
+ } else {
+ mScreenshotView.requestFocus();
+ mScreenshotView.setOnClickListener((v) -> {
+ // TODO: remove once we have a better UI to show that we aren't ready yet
+ Toast notReadyToast = Toast.makeText(
+ mContext, "Screenshot is not ready yet", Toast.LENGTH_SHORT);
+ notReadyToast.show();
+ });
+ saveScreenshotInWorkerThread(finisher, intent -> {
+ mScreenshotHandler.post(() -> mScreenshotView.setOnClickListener(v -> {
+ try {
+ intent.send();
+ clearScreenshot();
+ } catch (PendingIntent.CanceledException e) {
+ Log.e(TAG, "Edit intent cancelled", e);
+ }
+ mScreenshotHandler.removeMessages(MESSAGE_CORNER_TIMEOUT);
+ }));
+ return null;
+ });
+ mScreenshotHandler.sendMessageDelayed(
+ mScreenshotHandler.obtainMessage(MESSAGE_CORNER_TIMEOUT),
+ SCREENSHOT_CORNER_TIMEOUT_MILLIS);
+ }
}
});
- mScreenshotLayout.post(new Runnable() {
- @Override
- public void run() {
- // Play the shutter sound to notify that we've taken a screenshot
- mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
+ mScreenshotHandler.post(() -> {
+ // Play the shutter sound to notify that we've taken a screenshot
+ mCameraSound.play(MediaActionSound.SHUTTER_CLICK);
- mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
- mScreenshotView.buildLayer();
- mScreenshotAnimation.start();
- }
+ mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ mScreenshotView.buildLayer();
+ mScreenshotAnimation.start();
});
}
private ValueAnimator createScreenshotDropInAnimation() {
@@ -877,6 +1019,47 @@
return anim;
}
+ private ValueAnimator createScreenshotToCornerAnimation(int w, int h) {
+ ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
+ anim.setStartDelay(SCREENSHOT_DROP_OUT_DELAY);
+
+ final float scaleDurationPct =
+ (float) SCREENSHOT_DROP_OUT_SCALE_DURATION / SCREENSHOT_DROP_OUT_DURATION;
+ final Interpolator scaleInterpolator = new Interpolator() {
+ @Override
+ public float getInterpolation(float x) {
+ if (x < scaleDurationPct) {
+ // Decelerate, and scale the input accordingly
+ return (float) (1f - Math.pow(1f - (x / scaleDurationPct), 2f));
+ }
+ return 1f;
+ }
+ };
+
+ // Determine the bounds of how to scale
+ float halfScreenWidth = (w - 2f * mBgPadding) / 2f;
+ float halfScreenHeight = (h - 2f * mBgPadding) / 2f;
+ final float offsetPct = SCREENSHOT_CORNER_MIN_SCALE_OFFSET;
+ final PointF finalPos = new PointF(
+ -halfScreenWidth + (SCREENSHOT_CORNER_MIN_SCALE + offsetPct) * halfScreenWidth,
+ halfScreenHeight - (SCREENSHOT_CORNER_MIN_SCALE + offsetPct) * halfScreenHeight);
+
+ // Animate the screenshot to the bottom left corner
+ anim.setDuration(SCREENSHOT_DROP_OUT_DURATION);
+ anim.addUpdateListener(animation -> {
+ float t = (Float) animation.getAnimatedValue();
+ float scaleT = (SCREENSHOT_DROP_IN_MIN_SCALE + mBgPaddingScale)
+ - scaleInterpolator.getInterpolation(t)
+ * (SCREENSHOT_DROP_IN_MIN_SCALE - SCREENSHOT_CORNER_MIN_SCALE);
+ mBackgroundView.setAlpha((1f - t) * BACKGROUND_ALPHA);
+ mScreenshotView.setScaleX(scaleT);
+ mScreenshotView.setScaleY(scaleT);
+ mScreenshotView.setTranslationX(t * finalPos.x);
+ mScreenshotView.setTranslationY(t * finalPos.y);
+ });
+ return anim;
+ }
+
static void notifyScreenshotError(Context context, NotificationManager nManager, int msgResId) {
Resources r = context.getResources();
String errorMsg = r.getString(msgResId);
@@ -911,12 +1094,71 @@
nManager.notify(SystemMessage.NOTE_GLOBAL_SCREENSHOT, n);
}
+ @VisibleForTesting
+ static CompletableFuture<List<Notification.Action>> getSmartActionsFuture(Context context,
+ Bitmap image, ScreenshotNotificationSmartActionsProvider smartActionsProvider,
+ Handler handler, boolean smartActionsEnabled, boolean isManagedProfile) {
+ if (!smartActionsEnabled) {
+ Slog.i(TAG, "Screenshot Intelligence not enabled, returning empty list.");
+ return CompletableFuture.completedFuture(Collections.emptyList());
+ }
+ if (image.getConfig() != Bitmap.Config.HARDWARE) {
+ Slog.w(TAG, String.format(
+ "Bitmap expected: Hardware, Bitmap found: %s. Returning empty list.",
+ image.getConfig()));
+ return CompletableFuture.completedFuture(Collections.emptyList());
+ }
+
+ Slog.d(TAG, "Screenshot from a managed profile: " + isManagedProfile);
+ CompletableFuture<List<Notification.Action>> smartActionsFuture;
+ try {
+ ActivityManager.RunningTaskInfo runningTask =
+ ActivityManagerWrapper.getInstance().getRunningTask();
+ ComponentName componentName =
+ (runningTask != null && runningTask.topActivity != null)
+ ? runningTask.topActivity
+ : new ComponentName("", "");
+ smartActionsFuture = smartActionsProvider.getActions(image, context,
+ THREAD_POOL_EXECUTOR,
+ handler,
+ componentName,
+ isManagedProfile);
+ } catch (Throwable e) {
+ smartActionsFuture = CompletableFuture.completedFuture(Collections.emptyList());
+ Slog.e(TAG, "Failed to get future for screenshot notification smart actions.", e);
+ }
+ return smartActionsFuture;
+ }
+
+ @VisibleForTesting
+ static List<Notification.Action> getSmartActions(
+ CompletableFuture<List<Notification.Action>> smartActionsFuture, int timeoutMs) {
+ try {
+ long startTimeMs = SystemClock.uptimeMillis();
+ List<Notification.Action> actions = smartActionsFuture.get(timeoutMs,
+ TimeUnit.MILLISECONDS);
+ Slog.d(TAG, String.format("Wait time for smart actions: %d ms",
+ SystemClock.uptimeMillis() - startTimeMs));
+ return actions;
+ } catch (Throwable e) {
+ Slog.e(TAG, "Failed to obtain screenshot notification smart actions.", e);
+ return Collections.emptyList();
+ }
+ }
+
/**
* Receiver to proxy the share or edit intent, used to clean up the notification and send
* appropriate signals to the system (ie. to dismiss the keyguard if necessary).
*/
public static class ActionProxyReceiver extends BroadcastReceiver {
static final int CLOSE_WINDOWS_TIMEOUT_MILLIS = 3000;
+ private final StatusBar mStatusBar;
+
+ @Inject
+ public ActionProxyReceiver(Optional<Lazy<StatusBar>> statusBarLazy) {
+ Lazy<StatusBar> statusBar = statusBarLazy.orElse(null);
+ mStatusBar = statusBar != null ? statusBar.get() : null;
+ }
@Override
public void onReceive(Context context, final Intent intent) {
@@ -939,9 +1181,14 @@
intent.getBooleanExtra(EXTRA_DISALLOW_ENTER_PIP, false));
context.startActivityAsUser(actionIntent, opts.toBundle(), UserHandle.CURRENT);
};
- StatusBar statusBar = SysUiServiceProvider.getComponent(context, StatusBar.class);
- statusBar.executeRunnableDismissingKeyguard(startActivityRunnable, null,
- true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */);
+
+ if (mStatusBar != null) {
+ mStatusBar.executeRunnableDismissingKeyguard(startActivityRunnable, null,
+ true /* dismissShade */, true /* afterKeyguardGone */,
+ true /* deferred */);
+ } else {
+ startActivityRunnable.run();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
new file mode 100644
index 0000000..fa23bf7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsProvider.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot;
+
+import android.app.Notification;
+import android.content.ComponentName;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.os.Handler;
+import android.util.Log;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+
+/**
+ * This class can be overridden by a vendor-specific sys UI implementation,
+ * in order to provide smart actions in the screenshot notification.
+ */
+public class ScreenshotNotificationSmartActionsProvider {
+ private static final String TAG = "ScreenshotActions";
+
+ /**
+ * Default implementation that returns an empty list.
+ * This method is overridden in vendor-specific Sys UI implementation.
+ *
+ * @param bitmap The bitmap of the screenshot. The bitmap config must be {@link
+ * HARDWARE}.
+ * @param context The current app {@link Context}.
+ * @param executor A {@link Executor} that can be used to execute tasks in parallel.
+ * @param handler A {@link Handler} to possibly run UI-thread code.
+ * @param componentName Contains package and activity class names where the screenshot was
+ * taken. This is used as an additional signal to generate and rank more
+ * relevant actions.
+ * @param isManagedProfile The screenshot was taken for a work profile app.
+ */
+ public CompletableFuture<List<Notification.Action>> getActions(Bitmap bitmap, Context context,
+ Executor executor, Handler handler, ComponentName componentName,
+ boolean isManagedProfile) {
+ Log.d(TAG, "Returning empty smart action list.");
+ return CompletableFuture.completedFuture(Collections.emptyList());
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index 34b8bfe..20d24e6 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -27,10 +27,15 @@
import android.util.Log;
import android.view.WindowManager;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
public class TakeScreenshotService extends Service {
private static final String TAG = "TakeScreenshotService";
- private static GlobalScreenshot mScreenshot;
+ private final GlobalScreenshot mScreenshot;
+ private final UserManager mUserManager;
private Handler mHandler = new Handler() {
@Override
@@ -50,16 +55,12 @@
// If the storage for this user is locked, we have no place to store
// the screenshot, so skip taking it instead of showing a misleading
// animation and error notification.
- if (!getSystemService(UserManager.class).isUserUnlocked()) {
+ if (!mUserManager.isUserUnlocked()) {
Log.w(TAG, "Skipping screenshot because storage is locked!");
post(finisher);
return;
}
- if (mScreenshot == null) {
- mScreenshot = new GlobalScreenshot(TakeScreenshotService.this);
- }
-
switch (msg.what) {
case WindowManager.TAKE_SCREENSHOT_FULLSCREEN:
mScreenshot.takeScreenshot(finisher, msg.arg1 > 0, msg.arg2 > 0);
@@ -73,6 +74,12 @@
}
};
+ @Inject
+ public TakeScreenshotService(GlobalScreenshot globalScreenshot, UserManager userManager) {
+ mScreenshot = globalScreenshot;
+ mUserManager = userManager;
+ }
+
@Override
public IBinder onBind(Intent intent) {
return new Messenger(mHandler).getBinder();
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 176676f..b1f1f38 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -44,6 +44,7 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.systemui.Dependency;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import java.util.ArrayList;
@@ -281,12 +282,13 @@
}
};
- public BrightnessController(Context context, ToggleSlider control) {
+ public BrightnessController(Context context, ToggleSlider control,
+ BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mControl = control;
mControl.setMax(GAMMA_SPACE_MAX);
mBackgroundHandler = new Handler((Looper) Dependency.get(Dependency.BG_LOOPER));
- mUserTracker = new CurrentUserTracker(mContext) {
+ mUserTracker = new CurrentUserTracker(broadcastDispatcher) {
@Override
public void onUserSwitched(int newUserId) {
mBackgroundHandler.post(mUpdateModeRunnable);
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
index d8b4df5..70c2531 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
@@ -28,11 +28,21 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+
+import javax.inject.Inject;
/** A dialog that provides controls for adjusting the screen brightness. */
public class BrightnessDialog extends Activity {
private BrightnessController mBrightnessController;
+ private final BroadcastDispatcher mBroadcastDispatcher;
+
+ @Inject
+ public BrightnessDialog(BroadcastDispatcher broadcastDispatcher) {
+ mBroadcastDispatcher = broadcastDispatcher;
+ }
+
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -49,7 +59,7 @@
setContentView(v);
final ToggleSliderView slider = findViewById(R.id.brightness_slider);
- mBrightnessController = new BrightnessController(this, slider);
+ mBrightnessController = new BrightnessController(this, slider, mBroadcastDispatcher);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/settings/CurrentUserObservable.java b/packages/SystemUI/src/com/android/systemui/settings/CurrentUserObservable.java
index 3cf08b4..3cdc01d 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/CurrentUserObservable.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/CurrentUserObservable.java
@@ -16,11 +16,11 @@
package com.android.systemui.settings;
-import android.content.Context;
-
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+
/**
* A class that has an observable for the current user.
*/
@@ -42,8 +42,8 @@
}
};
- public CurrentUserObservable(Context context) {
- mTracker = new CurrentUserTracker(context) {
+ public CurrentUserObservable(BroadcastDispatcher broadcastDispatcher) {
+ mTracker = new CurrentUserTracker(broadcastDispatcher) {
@Override
public void onUserSwitched(int newUserId) {
mCurrentUser.setValue(newUserId);
diff --git a/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java b/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java
index 0b89dc1..9f79785 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/CurrentUserTracker.java
@@ -23,6 +23,7 @@
import android.content.IntentFilter;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import java.util.ArrayList;
import java.util.List;
@@ -33,8 +34,8 @@
private Consumer<Integer> mCallback = this::onUserSwitched;
- public CurrentUserTracker(Context context) {
- this(UserReceiver.getInstance(context));
+ public CurrentUserTracker(BroadcastDispatcher broadcastDispatcher) {
+ this(UserReceiver.getInstance(broadcastDispatcher));
}
@VisibleForTesting
@@ -60,20 +61,20 @@
static class UserReceiver extends BroadcastReceiver {
private static UserReceiver sInstance;
- private Context mAppContext;
private boolean mReceiverRegistered;
private int mCurrentUserId;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private List<Consumer<Integer>> mCallbacks = new ArrayList<>();
@VisibleForTesting
- UserReceiver(Context context) {
- mAppContext = context.getApplicationContext();
+ UserReceiver(BroadcastDispatcher broadcastDispatcher) {
+ mBroadcastDispatcher = broadcastDispatcher;
}
- static UserReceiver getInstance(Context context) {
+ static UserReceiver getInstance(BroadcastDispatcher broadcastDispatcher) {
if (sInstance == null) {
- sInstance = new UserReceiver(context);
+ sInstance = new UserReceiver(broadcastDispatcher);
}
return sInstance;
}
@@ -96,7 +97,7 @@
if (!mReceiverRegistered) {
mCurrentUserId = ActivityManager.getCurrentUser();
IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
- mAppContext.registerReceiver(this, filter);
+ mBroadcastDispatcher.registerReceiver(this, filter);
mReceiverRegistered = true;
}
}
@@ -105,7 +106,7 @@
if (mCallbacks.contains(callback)) {
mCallbacks.remove(callback);
if (mCallbacks.size() == 0 && mReceiverRegistered) {
- mAppContext.unregisterReceiver(this);
+ mBroadcastDispatcher.unregisterReceiver(this);
mReceiverRegistered = false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index df9791d..a571f01 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -34,13 +34,18 @@
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.stackdivider.DividerView;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Dispatches shortcut to System UI components
*/
+@Singleton
public class ShortcutKeyDispatcher extends SystemUI
implements ShortcutKeyServiceProxy.Callbacks {
private static final String TAG = "ShortcutKeyDispatcher";
+ private final Divider mDivider;
private ShortcutKeyServiceProxy mShortcutKeyServiceProxy = new ShortcutKeyServiceProxy(this);
private IWindowManager mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
@@ -53,8 +58,10 @@
protected final long SC_DOCK_LEFT = META_MASK | KeyEvent.KEYCODE_LEFT_BRACKET;
protected final long SC_DOCK_RIGHT = META_MASK | KeyEvent.KEYCODE_RIGHT_BRACKET;
- public ShortcutKeyDispatcher(Context context) {
+ @Inject
+ public ShortcutKeyDispatcher(Context context, Divider divider) {
super(context);
+ mDivider = divider;
}
/**
@@ -95,7 +102,7 @@
: SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT, null, -1);
} else {
// If there is already a docked window, we respond by resizing the docking pane.
- DividerView dividerView = getComponent(Divider.class).getView();
+ DividerView dividerView = mDivider.getView();
DividerSnapAlgorithm snapAlgorithm = dividerView.getSnapAlgorithm();
int dividerPosition = dividerView.getCurrentPosition();
DividerSnapAlgorithm.SnapTarget currentTarget =
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index c8b2b6a..d12f3ee 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -59,7 +59,6 @@
public void start() {
mWindowManager = new DividerWindowManager(mContext);
update(mContext.getResources().getConfiguration());
- putComponent(Divider.class, this);
mDockDividerVisibilityListener = new DockDividerVisibilityListener();
try {
WindowManagerGlobal.getWindowManagerService().registerDockedStackListener(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 34f5437..621f101 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -22,8 +22,6 @@
import static android.inputmethodservice.InputMethodService.IME_INVISIBLE;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
-import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
-import static android.view.InsetsState.TYPE_TOP_BAR;
import static com.android.systemui.statusbar.phone.StatusBar.ONLY_CORE_APPS;
@@ -34,7 +32,6 @@
import android.app.StatusBarManager.WindowVisibleState;
import android.content.ComponentName;
import android.content.Context;
-import android.graphics.Rect;
import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.hardware.display.DisplayManager;
import android.inputmethodservice.InputMethodService.BackDispositionMode;
@@ -45,18 +42,13 @@
import android.os.Message;
import android.util.Pair;
import android.util.SparseArray;
-import android.view.InsetsFlags;
import android.view.InsetsState.InternalInsetType;
-import android.view.View;
import android.view.WindowInsetsController.Appearance;
-import androidx.annotation.VisibleForTesting;
-
import com.android.internal.os.SomeArgs;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.view.AppearanceRegion;
-import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.policy.CallbackController;
@@ -304,7 +296,6 @@
}
}
- @VisibleForTesting
public CommandQueue(Context context) {
context.getSystemService(DisplayManager.class).registerDisplayListener(this, mHandler);
// We always have default display.
@@ -466,42 +457,6 @@
}
}
- // TODO(b/118118435): Remove this function after migration
- @Override
- public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenStackBounds, Rect dockedStackBounds,
- boolean navbarColorManagedByIme) {
- synchronized (mLock) {
- final boolean hasDockedStack = !dockedStackBounds.isEmpty();
- final boolean transientStatus = (vis & View.STATUS_BAR_TRANSIENT) != 0;
- final boolean transientNavigation = (vis & View.NAVIGATION_BAR_TRANSIENT) != 0;
- if (transientStatus && transientNavigation) {
- showTransient(displayId, new int[]{TYPE_TOP_BAR, TYPE_NAVIGATION_BAR});
- } else if (transientStatus) {
- showTransient(displayId, new int[]{TYPE_TOP_BAR});
- abortTransient(displayId, new int[]{TYPE_NAVIGATION_BAR});
- } else if (transientNavigation) {
- showTransient(displayId, new int[]{TYPE_NAVIGATION_BAR});
- abortTransient(displayId, new int[]{TYPE_TOP_BAR});
- } else {
- abortTransient(displayId, new int[]{TYPE_TOP_BAR, TYPE_NAVIGATION_BAR});
- }
- SomeArgs args = SomeArgs.obtain();
- args.argi1 = displayId;
- args.argi2 = InsetsFlags.getAppearance(vis);
- args.argi3 = navbarColorManagedByIme ? 1 : 0;
- final int fullscreenAppearance = InsetsFlags.getAppearance(fullscreenStackVis);
- final int dockedAppearance = InsetsFlags.getAppearance(dockedStackVis);
- args.arg1 = hasDockedStack
- ? new AppearanceRegion[]{
- new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds),
- new AppearanceRegion(dockedAppearance, dockedStackBounds)}
- : new AppearanceRegion[]{
- new AppearanceRegion(fullscreenAppearance, fullscreenStackBounds)};
- mHandler.obtainMessage(MSG_SYSTEM_BAR_APPEARANCE_CHANGED, args).sendToTarget();
- }
- }
-
@Override
public void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive) {
synchronized (mLock) {
@@ -1186,17 +1141,4 @@
}
}
}
-
- // Need this class since CommandQueue already extends IStatusBar.Stub, so CommandQueueStart
- // is needed so it can extend SystemUI.
- public static class CommandQueueStart extends SystemUI {
- public CommandQueueStart(Context context) {
- super(context);
- }
-
- @Override
- public void start() {
- putComponent(CommandQueue.class, new CommandQueue(mContext));
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
index 1f38904..9f5cf68 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -18,8 +18,6 @@
import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.systemui.SysUiServiceProvider.getComponent;
-
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.os.Handler;
@@ -66,14 +64,12 @@
SparseArray<NavigationBarFragment> mNavigationBars = new SparseArray<>();
@Inject
- public NavigationBarController(Context context, @MainHandler Handler handler) {
+ public NavigationBarController(Context context, @MainHandler Handler handler,
+ CommandQueue commandQueue) {
mContext = context;
mHandler = handler;
mDisplayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
- CommandQueue commandQueue = getComponent(mContext, CommandQueue.class);
- if (commandQueue != null) {
- commandQueue.addCallback(this);
- }
+ commandQueue.addCallback(this);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 7adf7af..571d3d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -46,6 +46,7 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.recents.OverviewProxyService;
@@ -90,6 +91,7 @@
private final UserManager mUserManager;
private final IStatusBarService mBarService;
private final List<UserChangedListener> mListeners = new ArrayList<>();
+ private final BroadcastDispatcher mBroadcastDispatcher;
private boolean mShowLockscreenNotifications;
private boolean mAllowLockscreenRemoteInput;
@@ -180,7 +182,8 @@
}
@Inject
- public NotificationLockscreenUserManagerImpl(Context context) {
+ public NotificationLockscreenUserManagerImpl(Context context,
+ BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
Context.DEVICE_POLICY_SERVICE);
@@ -191,6 +194,7 @@
Dependency.get(StatusBarStateController.class).addCallback(this);
mLockPatternUtils = new LockPatternUtils(context);
mKeyguardManager = context.getSystemService(KeyguardManager.class);
+ mBroadcastDispatcher = broadcastDispatcher;
}
public void setUpWithPresenter(NotificationPresenter presenter) {
@@ -244,15 +248,15 @@
UserHandle.USER_ALL);
}
- mContext.registerReceiverAsUser(mAllUsersReceiver, UserHandle.ALL,
+ mBroadcastDispatcher.registerReceiver(mAllUsersReceiver,
new IntentFilter(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED),
- null, null);
+ null /* handler */, UserHandle.ALL);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(Intent.ACTION_USER_ADDED);
filter.addAction(Intent.ACTION_USER_UNLOCKED);
- mContext.registerReceiver(mBaseBroadcastReceiver, filter);
+ mBroadcastDispatcher.registerReceiver(mBaseBroadcastReceiver, filter);
IntentFilter internalFilter = new IntentFilter();
internalFilter.addAction(NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index c838ac5..35f06f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -59,6 +59,7 @@
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.RemoteInputView;
import java.io.FileDescriptor;
@@ -121,6 +122,7 @@
private final UserManager mUserManager;
private final KeyguardManager mKeyguardManager;
private final StatusBarStateController mStatusBarStateController;
+ private final RemoteInputUriController mRemoteInputUriController;
protected RemoteInputController mRemoteInputController;
protected NotificationLifetimeExtender.NotificationSafeToRemoveCallback
@@ -260,7 +262,8 @@
NotificationEntryManager notificationEntryManager,
Lazy<ShadeController> shadeController,
StatusBarStateController statusBarStateController,
- @MainHandler Handler mainHandler) {
+ @MainHandler Handler mainHandler,
+ RemoteInputUriController remoteInputUriController) {
mContext = context;
mLockscreenUserManager = lockscreenUserManager;
mSmartReplyController = smartReplyController;
@@ -273,6 +276,7 @@
addLifetimeExtenders();
mKeyguardManager = context.getSystemService(KeyguardManager.class);
mStatusBarStateController = statusBarStateController;
+ mRemoteInputUriController = remoteInputUriController;
notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
@Override
@@ -300,7 +304,7 @@
/** Initializes this component with the provided dependencies. */
public void setUpWithCallback(Callback callback, RemoteInputController.Delegate delegate) {
mCallback = callback;
- mRemoteInputController = new RemoteInputController(delegate);
+ mRemoteInputController = new RemoteInputController(delegate, mRemoteInputUriController);
mRemoteInputController.addCallback(new RemoteInputController.Callback() {
@Override
public void onRemoteInputSent(NotificationEntry entry) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index d6b87af..20a3e35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -21,7 +21,6 @@
import android.os.Handler;
import android.os.Trace;
import android.os.UserHandle;
-import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -40,6 +39,7 @@
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.util.Assert;
+import com.android.systemui.util.Utils;
import java.util.ArrayList;
import java.util.HashMap;
@@ -146,9 +146,7 @@
final int N = activeNotifications.size();
for (int i = 0; i < N; i++) {
NotificationEntry ent = activeNotifications.get(i);
- int flag = Settings.System.getInt(mContext.getContentResolver(),
- "qs_media_player", 0);
- boolean hideMedia = (flag == 1);
+ boolean hideMedia = Utils.useQsMediaPlayer(mContext);
if (ent.isRowDismissed() || ent.isRowRemoved()
|| (ent.isMediaNotification() && hideMedia)
|| mBubbleController.isBubbleNotificationSuppressedFromShade(ent.getKey())) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
index 998cf52..778443c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
@@ -19,12 +19,15 @@
import android.app.Notification;
import android.app.RemoteInput;
import android.content.Context;
+import android.net.Uri;
import android.os.SystemProperties;
+import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.util.Pair;
import com.android.internal.util.Preconditions;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.RemoteInputView;
import java.lang.ref.WeakReference;
@@ -43,9 +46,12 @@
private final ArrayMap<String, Object> mSpinning = new ArrayMap<>();
private final ArrayList<Callback> mCallbacks = new ArrayList<>(3);
private final Delegate mDelegate;
+ private final RemoteInputUriController mRemoteInputUriController;
- public RemoteInputController(Delegate delegate) {
+ public RemoteInputController(Delegate delegate,
+ RemoteInputUriController remoteInputUriController) {
mDelegate = delegate;
+ mRemoteInputUriController = remoteInputUriController;
}
/**
@@ -272,6 +278,14 @@
mDelegate.lockScrollTo(entry);
}
+ /**
+ * Create a temporary grant which allows the app that submitted the notification access to the
+ * specified URI.
+ */
+ public void grantInlineReplyUriPermission(StatusBarNotification sbn, Uri data) {
+ mRemoteInputUriController.grantInlineReplyUriPermission(sbn, data);
+ }
+
public interface Callback {
default void onRemoteInputActive(boolean active) {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java
new file mode 100644
index 0000000..d1f6ebf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarDependenciesModule.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+
+import javax.inject.Singleton;
+
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger Module providing common dependencies of StatusBar.
+ */
+@Module
+public class StatusBarDependenciesModule {
+ /**
+ * Provides our instance of CommandQueue which is considered optional.
+ */
+ @Provides
+ @Singleton
+ public CommandQueue provideCommandQueue(Context context) {
+ return new CommandQueue(context);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java
new file mode 100644
index 0000000..bc7c22d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SuperStatusBarViewFactory.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.StatusBarWindowView;
+import com.android.systemui.util.InjectionInflationController;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Creates a single instance of super_status_bar that can be shared across various system ui
+ * objects.
+ */
+@Singleton
+public class SuperStatusBarViewFactory {
+
+ private final Context mContext;
+ private final InjectionInflationController mInjectionInflationController;
+
+ private StatusBarWindowView mStatusBarWindowView;
+ private NotificationShelf mNotificationShelf;
+
+ @Inject
+ public SuperStatusBarViewFactory(Context context,
+ InjectionInflationController injectionInflationController) {
+ mContext = context;
+ mInjectionInflationController = injectionInflationController;
+ }
+
+ /**
+ * Gets the inflated {@link StatusBarWindowView} from {@link R.layout#super_status_bar}. Returns
+ * a cached instance, if it has already been inflated.
+ */
+ public StatusBarWindowView getStatusBarWindowView() {
+ if (mStatusBarWindowView != null) {
+ return mStatusBarWindowView;
+ }
+
+ mStatusBarWindowView = (StatusBarWindowView) mInjectionInflationController.injectable(
+ LayoutInflater.from(mContext)).inflate(R.layout.super_status_bar,
+ /* root= */ null);
+ if (mStatusBarWindowView == null) {
+ throw new IllegalStateException(
+ "R.layout.super_status_bar could not be properly inflated");
+ }
+ return mStatusBarWindowView;
+ }
+
+ /**
+ * Gets the inflated {@link NotificationShelf} from
+ * {@link R.layout#status_bar_notification_shelf}.
+ * Returns a cached instance, if it has already been inflated.
+ *
+ * @param container the expected container to hold the {@link NotificationShelf}. The view
+ * isn't immediately attached, but the layout params of this view is used
+ * during inflation.
+ */
+ public NotificationShelf getNotificationShelf(ViewGroup container) {
+ if (mNotificationShelf != null) {
+ return mNotificationShelf;
+ }
+
+ mNotificationShelf = (NotificationShelf) mInjectionInflationController.injectable(
+ LayoutInflater.from(mContext)).inflate(R.layout.status_bar_notification_shelf,
+ container, /* attachToRoot= */ false);
+ if (mNotificationShelf == null) {
+ throw new IllegalStateException(
+ "R.layout.status_bar_notification_shelf could not be properly inflated");
+ }
+ return mNotificationShelf;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index 53fbe5b..49bed15 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -53,7 +53,6 @@
import com.android.systemui.Dependency;
import com.android.systemui.DockedStackExistsListener;
import com.android.systemui.R;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.SystemUI;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.statusbar.CommandQueue;
@@ -62,9 +61,13 @@
import java.util.List;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/** The class to show notification(s) of instant apps. This may show multiple notifications on
* splitted screen.
*/
+@Singleton
public class InstantAppNotifier extends SystemUI
implements CommandQueue.Callbacks, KeyguardStateController.Callback {
private static final String TAG = "InstantAppNotifier";
@@ -73,11 +76,14 @@
private final Handler mHandler = new Handler();
private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
+ private final CommandQueue mCommandQueue;
private boolean mDockedStackExists;
private KeyguardStateController mKeyguardStateController;
- public InstantAppNotifier(Context context) {
+ @Inject
+ public InstantAppNotifier(Context context, CommandQueue commandQueue) {
super(context);
+ mCommandQueue = commandQueue;
}
@Override
@@ -91,7 +97,7 @@
// Ignore
}
- SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this);
+ mCommandQueue.addCallback(this);
mKeyguardStateController.addCallback(this);
DockedStackExistsListener.register(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
index 9981c93..a0229d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
@@ -68,7 +68,6 @@
private final ArrayMap<String, NotificationEntry> mEntries = new ArrayMap<>();
private final ArrayList<NotificationEntry> mSortedAndFiltered = new ArrayList<>();
- private final ArrayList<NotificationEntry> mFilteredForUser = new ArrayList<>();
private final NotificationGroupManager mGroupManager =
Dependency.get(NotificationGroupManager.class);
@@ -166,20 +165,20 @@
}
public ArrayList<NotificationEntry> getNotificationsForCurrentUser() {
- mFilteredForUser.clear();
-
synchronized (mEntries) {
final int len = mEntries.size();
+ ArrayList<NotificationEntry> filteredForUser = new ArrayList<>(len);
+
for (int i = 0; i < len; i++) {
NotificationEntry entry = mEntries.valueAt(i);
final StatusBarNotification sbn = entry.getSbn();
if (!getEnvironment().isNotificationForCurrentProfiles(sbn)) {
continue;
}
- mFilteredForUser.add(entry);
+ filteredForUser.add(entry);
}
+ return filteredForUser;
}
- return mFilteredForUser;
}
public NotificationEntry get(String key) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
index 396c5fe..0ef75165 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
@@ -142,6 +142,7 @@
entry.updateIcons(mContext, sbn);
entry.reset();
updateNotification(entry, pmUser, sbn, entry.getRow());
+ entry.getRow().setOnDismissRunnable(onDismissRunnable);
} else {
entry.createIcons(mContext, sbn);
new RowInflaterTask().inflate(mContext, parent, entry,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index a817f54..50a2037 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -159,6 +159,8 @@
private int mHeadsUpAddStartLocation;
private float mHeadsUpLocation;
private boolean mIsAppearing;
+ private boolean mDismissed;
+ private boolean mRefocusOnDismiss;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -1048,6 +1050,27 @@
return getHeight();
}
+ /** Mark that this view has been dismissed. */
+ public void dismiss(boolean refocusOnDismiss) {
+ mDismissed = true;
+ mRefocusOnDismiss = refocusOnDismiss;
+ }
+
+ /** Mark that this view is no longer dismissed. */
+ public void unDismiss() {
+ mDismissed = false;
+ }
+
+ /** Is this view marked as dismissed? */
+ public boolean isDismissed() {
+ return mDismissed;
+ }
+
+ /** Should a re-focus occur upon dismissing this view? */
+ public boolean shouldRefocusOnDismiss() {
+ return mRefocusOnDismiss || isAccessibilityFocused();
+ }
+
public interface OnActivatedListener {
void onActivated(ActivatableNotificationView view);
void onActivationReset(ActivatableNotificationView view);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 536db67..f0d07a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -95,6 +95,7 @@
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.SwipeableView;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -114,7 +115,7 @@
* the group summary (which contains 1 or more child notifications).
*/
public class ExpandableNotificationRow extends ActivatableNotificationView
- implements PluginListener<NotificationMenuRowPlugin> {
+ implements PluginListener<NotificationMenuRowPlugin>, SwipeableView {
private static final boolean DEBUG = false;
private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
@@ -288,7 +289,6 @@
}
};
private boolean mForceUnlocked;
- private boolean mDismissed;
private boolean mKeepInParent;
private boolean mRemoved;
private static final Property<ExpandableNotificationRow, Float> TRANSLATE_CONTENT =
@@ -307,7 +307,6 @@
private boolean mHeadsupDisappearRunning;
private View mChildAfterViewWhenDismissed;
private View mGroupParentWhenDismissed;
- private boolean mRefocusOnDismiss;
private float mContentTransformationAmount;
private boolean mIconsVisible = true;
private boolean mAboveShelf;
@@ -1164,6 +1163,11 @@
}
}
+ @Override
+ public boolean hasFinishedInitialization() {
+ return getEntry().hasFinishedInitialization();
+ }
+
/**
* Get a handle to a NotificationMenuRowPlugin whose menu view has been added to our hierarchy,
* or null if there is no menu row
@@ -1323,11 +1327,11 @@
}
}
- public void setDismissed(boolean fromAccessibility) {
+ @Override
+ public void dismiss(boolean refocusOnDismiss) {
+ super.dismiss(refocusOnDismiss);
setLongPressListener(null);
- mDismissed = true;
mGroupParentWhenDismissed = mNotificationParent;
- mRefocusOnDismiss = fromAccessibility;
mChildAfterViewWhenDismissed = null;
mEntry.icon.setDismissed();
if (isChildInGroup()) {
@@ -1340,10 +1344,6 @@
}
}
- public boolean isDismissed() {
- return mDismissed;
- }
-
public boolean keepInParent() {
return mKeepInParent;
}
@@ -1445,7 +1445,7 @@
groupSummary.getRow().performDismiss(fromAccessibility);
}
}
- setDismissed(fromAccessibility);
+ dismiss(fromAccessibility);
if (mEntry.isClearable()) {
// TODO: beverlyt, log dismissal
// TODO: track dismiss sentiment
@@ -3021,10 +3021,6 @@
return false;
}
- public boolean shouldRefocusOnDismiss() {
- return mRefocusOnDismiss || isAccessibilityFocused();
- }
-
public interface OnExpandClickListener {
void onExpandClicked(NotificationEntry clickedEntry, boolean nowExpanded);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index 9bc0ca4..d0122c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -28,7 +28,6 @@
import android.media.session.PlaybackState;
import android.metrics.LogMaker;
import android.os.Handler;
-import android.provider.Settings;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
@@ -48,6 +47,7 @@
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
+import com.android.systemui.util.Utils;
import java.util.Timer;
import java.util.TimerTask;
@@ -182,8 +182,7 @@
final MediaSession.Token token = mRow.getEntry().getSbn().getNotification().extras
.getParcelable(Notification.EXTRA_MEDIA_SESSION);
- int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0);
- if (flag == 1) {
+ if (Utils.useQsMediaPlayer(mContext)) {
StatusBarWindowController ctrl = Dependency.get(StatusBarWindowController.class);
QuickQSPanel panel = ctrl.getStatusBarView().findViewById(
com.android.systemui.R.id.quick_qs_panel);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
index 54d4066..fdd51e9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
@@ -23,7 +23,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.PendingIntent;
import android.content.Intent;
import android.provider.Settings;
import android.view.LayoutInflater;
@@ -310,6 +309,8 @@
mParent.removeView(mPeopleHubView);
}
} else {
+ mPeopleHubView.unDismiss();
+ mPeopleHubView.resetTranslation();
if (!currentlyVisible) {
if (mPeopleHubView.getTransientContainer() != null) {
mPeopleHubView.getTransientContainer().removeTransientView(mPeopleHubView);
@@ -419,8 +420,9 @@
}
}
- private void handlePeopleHubClick(PendingIntent pendingIntent) {
- mActivityStarter.startPendingIntentDismissingKeyguard(pendingIntent, null, mPeopleHubView);
+ void hidePeopleRow() {
+ mPeopleHubVisible = false;
+ updateSectionBoundaries();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 6dca7ee..2b9912c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -4920,7 +4920,7 @@
} else {
child.setMinClipTopAmount(0);
}
- previousChildWillBeDismissed = StackScrollAlgorithm.canChildBeDismissed(child);
+ previousChildWillBeDismissed = canChildBeDismissed(child);
}
}
@@ -5523,7 +5523,7 @@
performDismissAllAnimations(viewsToHide, closeShade, () -> {
for (ExpandableNotificationRow rowToRemove : viewsToRemove) {
- if (StackScrollAlgorithm.canChildBeDismissed(rowToRemove)) {
+ if (canChildBeDismissed(rowToRemove)) {
if (selection == ROWS_ALL) {
// TODO: This is a listener method; we shouldn't be calling it. Can we just
// call performRemoveNotification as below?
@@ -5552,7 +5552,7 @@
private boolean includeChildInDismissAll(
ExpandableNotificationRow row,
@SelectedRows int selection) {
- return StackScrollAlgorithm.canChildBeDismissed(row) && matchesSelection(row, selection);
+ return canChildBeDismissed(row) && matchesSelection(row, selection);
}
/**
@@ -6223,7 +6223,10 @@
*/
@Override
public void onChildDismissed(View view) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+ if (!(view instanceof ActivatableNotificationView)) {
+ return;
+ }
+ ActivatableNotificationView row = (ActivatableNotificationView) view;
if (!row.isDismissed()) {
handleChildViewDismissed(view);
}
@@ -6261,6 +6264,12 @@
row.performDismissWithBlockingHelper(false /* fromAccessibility */);
}
+ if (view instanceof PeopleHubView) {
+ PeopleHubView row = (PeopleHubView) view;
+ row.dismiss(false);
+ mSectionsManager.hidePeopleRow();
+ }
+
if (!isBlockingHelperShown) {
mSwipedOutViews.add(view);
}
@@ -6349,9 +6358,9 @@
return 0;
}
- @Override
+ @Override
public boolean canChildBeDismissed(View v) {
- return StackScrollAlgorithm.canChildBeDismissed(v);
+ return NotificationStackScrollLayout.canChildBeDismissed(v);
}
@Override
@@ -6361,6 +6370,23 @@
}
};
+ private static boolean canChildBeDismissed(View v) {
+ if (v instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+ if (row.isBlockingHelperShowingAndTranslationFinished()) {
+ return true;
+ }
+ if (row.areGutsExposed() || !row.getEntry().hasFinishedInitialization()) {
+ return false;
+ }
+ return row.canViewBeDismissed();
+ }
+ if (v instanceof PeopleHubView) {
+ return true;
+ }
+ return false;
+ }
+
// ---------------------- DragDownHelper.OnDragDownListener ------------------------------------
@ShadeViewRefactor(RefactorComponent.INPUT)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index 0968674..6d0fcc3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -31,11 +31,10 @@
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
-class NotificationSwipeHelper extends SwipeHelper
- implements NotificationSwipeActionHelper {
+class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeActionHelper {
+
@VisibleForTesting
protected static final long COVER_MENU_DELAY = 4000;
private static final String TAG = "NotificationSwipeHelper";
@@ -58,12 +57,7 @@
super(swipeDirection, callback, context, falsingManager);
mMenuListener = menuListener;
mCallback = callback;
- mFalsingCheck = new Runnable() {
- @Override
- public void run() {
- resetExposedMenuView(true /* animate */, true /* force */);
- }
- };
+ mFalsingCheck = () -> resetExposedMenuView(true /* animate */, true /* force */);
}
public View getTranslatingParentView() {
@@ -126,14 +120,14 @@
// Slide back any notifications that might be showing a menu
resetExposedMenuView(true /* animate */, false /* force */);
- if (currView instanceof ExpandableNotificationRow) {
- initializeRow((ExpandableNotificationRow) currView);
+ if (currView instanceof SwipeableView) {
+ initializeRow((SwipeableView) currView);
}
}
@VisibleForTesting
- protected void initializeRow(ExpandableNotificationRow row) {
- if (row.getEntry().hasFinishedInitialization()) {
+ protected void initializeRow(SwipeableView row) {
+ if (row.hasFinishedInitialization()) {
mCurrMenuRow = row.createMenu();
if (mCurrMenuRow != null) {
mCurrMenuRow.setMenuClickListener(mMenuListener);
@@ -304,8 +298,8 @@
@Override
public Animator getViewTranslationAnimator(View v, float target,
ValueAnimator.AnimatorUpdateListener listener) {
- if (v instanceof ExpandableNotificationRow) {
- return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener);
+ if (v instanceof SwipeableView) {
+ return ((SwipeableView) v).getTranslateViewAnimator(target, listener);
} else {
return superGetViewTranslationAnimator(v, target, listener);
}
@@ -313,15 +307,15 @@
@Override
public void setTranslation(View v, float translate) {
- if (v instanceof ExpandableNotificationRow) {
- ((ExpandableNotificationRow) v).setTranslation(translate);
+ if (v instanceof SwipeableView) {
+ ((SwipeableView) v).setTranslation(translate);
}
}
@Override
public float getTranslation(View v) {
- if (v instanceof ExpandableNotificationRow) {
- return ((ExpandableNotificationRow) v).getTranslation();
+ if (v instanceof SwipeableView) {
+ return ((SwipeableView) v).getTranslation();
}
else {
return 0f;
@@ -410,8 +404,8 @@
if (anim != null) {
anim.start();
}
- } else if (prevMenuExposedView instanceof ExpandableNotificationRow) {
- ExpandableNotificationRow row = (ExpandableNotificationRow) prevMenuExposedView;
+ } else if (prevMenuExposedView instanceof SwipeableView) {
+ SwipeableView row = (SwipeableView) prevMenuExposedView;
if (!row.isRemoved()) {
row.resetTranslation();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
index e31ee02..a079606 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
@@ -16,23 +16,39 @@
package com.android.systemui.statusbar.notification.stack
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.animation.ObjectAnimator
+import android.animation.ValueAnimator
import android.content.Context
import android.util.AttributeSet
+import android.util.FloatProperty
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.android.systemui.R
-import com.android.systemui.statusbar.notification.people.PersonViewModel
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin
import com.android.systemui.statusbar.notification.people.DataListener
+import com.android.systemui.statusbar.notification.people.PersonViewModel
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView
+private val TRANSLATE_CONTENT = object : FloatProperty<PeopleHubView>("translate") {
+ override fun setValue(view: PeopleHubView, value: Float) {
+ view.translation = value
+ }
+
+ override fun get(view: PeopleHubView) = view.translation
+}
+
class PeopleHubView(context: Context, attrs: AttributeSet) :
- ActivatableNotificationView(context, attrs) {
+ ActivatableNotificationView(context, attrs), SwipeableView {
private lateinit var contents: ViewGroup
private lateinit var personControllers: List<PersonDataListenerImpl>
+ private var translateAnim: ObjectAnimator? = null
+
val personViewAdapters: Sequence<DataListener<PersonViewModel?>>
get() = personControllers.asSequence()
@@ -49,6 +65,34 @@
override fun getContentView(): View = contents
+ override fun hasFinishedInitialization(): Boolean = true
+
+ override fun createMenu(): NotificationMenuRowPlugin? = null
+
+ override fun getTranslateViewAnimator(
+ leftTarget: Float,
+ listener: ValueAnimator.AnimatorUpdateListener?
+ ): Animator =
+ ObjectAnimator
+ .ofFloat(this, TRANSLATE_CONTENT, leftTarget)
+ .apply {
+ listener?.let { addUpdateListener(listener) }
+ addListener(object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(anim: Animator) {
+ translateAnim = null
+ }
+ })
+ }
+ .also {
+ translateAnim?.cancel()
+ translateAnim = it
+ }
+
+ override fun resetTranslation() {
+ translateAnim?.cancel()
+ translationX = 0f
+ }
+
private inner class PersonDataListenerImpl(val viewGroup: ViewGroup) :
DataListener<PersonViewModel?> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 4b61064..9646c01 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -195,20 +195,6 @@
}
}
- public static boolean canChildBeDismissed(View v) {
- if (!(v instanceof ExpandableNotificationRow)) {
- return false;
- }
- ExpandableNotificationRow row = (ExpandableNotificationRow) v;
- if (row.isBlockingHelperShowingAndTranslationFinished()) {
- return true;
- }
- if (row.areGutsExposed() || !row.getEntry().hasFinishedInitialization()) {
- return false;
- }
- return row.canViewBeDismissed();
- }
-
/**
* Updates the dimmed, activated and hiding sensitive states of the children.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SwipeableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SwipeableView.java
new file mode 100644
index 0000000..6c6ef61
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SwipeableView.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.stack;
+
+import android.animation.Animator;
+import android.animation.ValueAnimator;
+
+import androidx.annotation.Nullable;
+
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
+
+/** A View that is swipeable inside of the notification shade. */
+public interface SwipeableView {
+
+ /** Has this view finished initializing? */
+ boolean hasFinishedInitialization();
+
+ /** Optionally creates a menu for this view. */
+ @Nullable NotificationMenuRowPlugin createMenu();
+
+ /** Animator for translating the view, simulating a swipe. */
+ Animator getTranslateViewAnimator(
+ float leftTarget, ValueAnimator.AnimatorUpdateListener listener);
+
+ /** Sets the translation amount for an in-progress swipe. */
+ void setTranslation(float translate);
+
+ /** Gets the current translation amount. */
+ float getTranslation();
+
+ /** Has this view been removed? */
+ boolean isRemoved();
+
+ /** Resets the swipe translation back to zero state. */
+ void resetTranslation();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 1e8e28f..865d7e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -35,6 +35,8 @@
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dependency;
+import com.android.systemui.DumpController;
+import com.android.systemui.Dumpable;
import com.android.systemui.dagger.qualifiers.MainResources;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
@@ -42,6 +44,7 @@
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -53,7 +56,7 @@
* Controller which coordinates all the biometric unlocking actions with the UI.
*/
@Singleton
-public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
+public class BiometricUnlockController extends KeyguardUpdateMonitorCallback implements Dumpable {
private static final String TAG = "BiometricUnlockCtrl";
private static final boolean DEBUG_BIO_WAKELOCK = KeyguardConstants.DEBUG_BIOMETRIC_WAKELOCK;
@@ -160,7 +163,7 @@
KeyguardUpdateMonitor keyguardUpdateMonitor,
@MainResources Resources resources,
KeyguardBypassController keyguardBypassController, DozeParameters dozeParameters,
- MetricsLogger metricsLogger) {
+ MetricsLogger metricsLogger, DumpController dumpController) {
mContext = context;
mPowerManager = context.getSystemService(PowerManager.class);
mUpdateMonitor = keyguardUpdateMonitor;
@@ -180,6 +183,7 @@
mKeyguardBypassController = keyguardBypassController;
mKeyguardBypassController.setUnlockController(this);
mMetricsLogger = metricsLogger;
+ dumpController.registerDumpable(this);
}
public void setStatusBarKeyguardViewManager(
@@ -543,7 +547,8 @@
return mHasScreenTurnedOnSinceAuthenticating;
}
- public void dump(PrintWriter pw) {
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(" BiometricUnlockController:");
pw.print(" mMode="); pw.println(mMode);
pw.print(" mWakeLock="); pw.println(mWakeLock);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
index fce1dcc..c273108 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ButtonDispatcher.java
@@ -203,10 +203,16 @@
mFadeAnimator.addUpdateListener(mAlphaListener);
mFadeAnimator.start();
} else {
- mAlpha = alpha;
- final int N = mViews.size();
- for (int i = 0; i < N; i++) {
- mViews.get(i).setAlpha(alpha);
+ // Discretize the alpha updates to prevent too frequent updates when there is a long
+ // alpha animation
+ int prevAlpha = (int) (getAlpha() * 255);
+ int nextAlpha = (int) (alpha * 255);
+ if (prevAlpha != nextAlpha) {
+ mAlpha = nextAlpha / 255f;
+ final int N = mViews.size();
+ for (int i = 0; i < N; i++) {
+ mViews.get(i).setAlpha(mAlpha);
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
index e78b85e..0092cc9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
@@ -83,7 +83,7 @@
mNetworkController = Dependency.get(NetworkController.class);
mStatusBarStateController = Dependency.get(StatusBarStateController.class);
mStatusBarComponent = SysUiServiceProvider.getComponent(getContext(), StatusBar.class);
- mCommandQueue = SysUiServiceProvider.getComponent(getContext(), CommandQueue.class);
+ mCommandQueue = Dependency.get(CommandQueue.class);
}
@Override
@@ -100,7 +100,8 @@
mStatusBar.restoreHierarchyState(
savedInstanceState.getSparseParcelableArray(EXTRA_PANEL_STATE));
}
- mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons));
+ mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons),
+ Dependency.get(CommandQueue.class));
mDarkIconManager.setShouldLog(true);
Dependency.get(StatusBarIconController.class).addIconGroup(mDarkIconManager);
mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
index ac58e68..ef0f7cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
@@ -26,6 +26,7 @@
import com.android.systemui.R;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
+import com.android.systemui.statusbar.CommandQueue;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -51,11 +52,11 @@
/**
*/
@Inject
- public DarkIconDispatcherImpl(Context context) {
+ public DarkIconDispatcherImpl(Context context, CommandQueue commandQueue) {
mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
- mTransitionsController = new LightBarTransitionsController(context, this);
+ mTransitionsController = new LightBarTransitionsController(context, this, commandQueue);
}
public LightBarTransitionsController getTransitionsController() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index ce96005..8e5a912 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.SysUiServiceProvider.getComponent;
-
import android.graphics.Point;
import android.graphics.Rect;
import android.view.DisplayCutout;
@@ -94,14 +92,14 @@
public HeadsUpAppearanceController(
NotificationIconAreaController notificationIconAreaController,
- HeadsUpManagerPhone headsUpManager,
- View statusbarView,
+ HeadsUpManagerPhone headsUpManager, View statusbarView,
SysuiStatusBarStateController statusBarStateController,
KeyguardBypassController keyguardBypassController,
KeyguardStateController keyguardStateController,
- NotificationWakeUpCoordinator wakeUpCoordinator) {
+ NotificationWakeUpCoordinator wakeUpCoordinator, CommandQueue commandQueue) {
this(notificationIconAreaController, headsUpManager, statusBarStateController,
keyguardBypassController, wakeUpCoordinator, keyguardStateController,
+ commandQueue,
statusbarView.findViewById(R.id.heads_up_status_bar_view),
statusbarView.findViewById(R.id.notification_stack_scroller),
statusbarView.findViewById(R.id.notification_panel),
@@ -118,6 +116,7 @@
KeyguardBypassController bypassController,
NotificationWakeUpCoordinator wakeUpCoordinator,
KeyguardStateController keyguardStateController,
+ CommandQueue commandQueue,
HeadsUpStatusBarView headsUpStatusBarView,
NotificationStackScrollLayout stackScroller,
NotificationPanelView panelView,
@@ -161,7 +160,7 @@
mStatusBarStateController = stateController;
mWakeUpCoordinator = wakeUpCoordinator;
wakeUpCoordinator.addListener(this);
- mCommandQueue = getComponent(headsUpStatusBarView.getContext(), CommandQueue.class);
+ mCommandQueue = commandQueue;
mKeyguardStateController = keyguardStateController;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
index aca7f44..f7d52b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
@@ -20,17 +20,20 @@
import android.content.pm.PackageManager
import android.hardware.biometrics.BiometricSourceType
import android.provider.Settings
+import com.android.systemui.DumpController
+import com.android.systemui.Dumpable
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.tuner.TunerService
+import java.io.FileDescriptor
import java.io.PrintWriter
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
-class KeyguardBypassController {
+class KeyguardBypassController : Dumpable {
private val mKeyguardStateController: KeyguardStateController
private val statusBarStateController: StatusBarStateController
@@ -68,7 +71,8 @@
tunerService: TunerService,
statusBarStateController: StatusBarStateController,
lockscreenUserManager: NotificationLockscreenUserManager,
- keyguardStateController: KeyguardStateController
+ keyguardStateController: KeyguardStateController,
+ dumpController: DumpController
) {
this.mKeyguardStateController = keyguardStateController
this.statusBarStateController = statusBarStateController
@@ -78,6 +82,7 @@
return
}
+ dumpController.registerDumpable("KeyguardBypassController", this)
statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
override fun onStateChanged(newState: Int) {
if (newState != StatusBarState.KEYGUARD) {
@@ -155,16 +160,16 @@
pendingUnlockType = null
}
- fun dump(pw: PrintWriter) {
+ override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
pw.println("KeyguardBypassController:")
- pw.print(" pendingUnlockType: "); pw.println(pendingUnlockType)
- pw.print(" bypassEnabled: "); pw.println(bypassEnabled)
- pw.print(" canBypass: "); pw.println(canBypass())
- pw.print(" bouncerShowing: "); pw.println(bouncerShowing)
- pw.print(" isPulseExpanding: "); pw.println(isPulseExpanding)
- pw.print(" launchingAffordance: "); pw.println(launchingAffordance)
- pw.print(" qSExpanded: "); pw.println(qSExpanded)
- pw.print(" hasFaceFeature: "); pw.println(hasFaceFeature)
+ pw.println(" pendingUnlockType: $pendingUnlockType")
+ pw.println(" bypassEnabled: $bypassEnabled")
+ pw.println(" canBypass: ${canBypass()}")
+ pw.println(" bouncerShowing: $bouncerShowing")
+ pw.println(" isPulseExpanding: $isPulseExpanding")
+ pw.println(" launchingAffordance: $launchingAffordance")
+ pw.println(" qSExpanded: $qSExpanded")
+ pw.println(" hasFaceFeature: $hasFaceFeature")
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 179375e..4e91e4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -240,7 +240,7 @@
* @return Alpha from 0 to 1.
*/
private float getClockAlpha(int y) {
- float alphaKeyguard = Math.max(0, y / Math.max(1f, getExpandedPreferredClockY()));
+ float alphaKeyguard = Math.max(0, y / Math.max(1f, getClockY(1f)));
alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard);
return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
index bf88704..2258c77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -21,21 +21,27 @@
import android.hardware.TriggerEventListener
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.systemui.DumpController
+import com.android.systemui.Dumpable
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.util.Assert
import com.android.systemui.util.sensors.AsyncSensorManager
+import java.io.FileDescriptor
+import java.io.PrintWriter
class KeyguardLiftController constructor(
private val statusBarStateController: StatusBarStateController,
private val asyncSensorManager: AsyncSensorManager,
- private val keyguardUpdateMonitor: KeyguardUpdateMonitor
-) : StatusBarStateController.StateListener, KeyguardUpdateMonitorCallback() {
+ private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
+ dumpController: DumpController
+) : StatusBarStateController.StateListener, Dumpable, KeyguardUpdateMonitorCallback() {
private val pickupSensor = asyncSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE)
private var isListening = false
private var bouncerVisible = false
init {
+ dumpController.registerDumpable(this)
statusBarStateController.addCallback(this)
keyguardUpdateMonitor.registerCallback(this)
updateListeningState()
@@ -64,6 +70,13 @@
updateListeningState()
}
+ override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
+ pw.println("KeyguardLiftController:")
+ pw.println(" pickupSensor: $pickupSensor")
+ pw.println(" isListening: $isListening")
+ pw.println(" bouncerVisible: $bouncerVisible")
+ }
+
private fun updateListeningState() {
if (pickupSensor == null) {
return
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 6ee031a..b24942a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -46,6 +46,7 @@
import com.android.systemui.R;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.qs.QSPanel;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
@@ -329,7 +330,8 @@
mMultiUserSwitch.setUserSwitcherController(mUserSwitcherController);
userInfoController.reloadUserInfo();
Dependency.get(ConfigurationController.class).addCallback(this);
- mIconManager = new TintedIconManager(findViewById(R.id.statusIcons));
+ mIconManager = new TintedIconManager(findViewById(R.id.statusIcons),
+ Dependency.get(CommandQueue.class));
Dependency.get(StatusBarIconController.class).addIconGroup(mIconManager);
onThemeChanged();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 2e776e3..1532c4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -247,7 +247,7 @@
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("LightBarController: ");
- pw.print(" mAppearance=0x"); pw.println(ViewDebug.flagsToString(
+ pw.print(" mAppearance="); pw.println(ViewDebug.flagsToString(
InsetsFlags.class, "appearance", mAppearance));
final int numStacks = mAppearanceRegions.length;
for (int i = 0; i < numStacks; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index de660ce1..092dd49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -27,7 +27,6 @@
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.Interpolators;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
@@ -49,6 +48,7 @@
private final DarkIntensityApplier mApplier;
private final KeyguardStateController mKeyguardStateController;
private final StatusBarStateController mStatusBarStateController;
+ private final CommandQueue mCommandQueue;
private boolean mTransitionDeferring;
private long mTransitionDeferringStartTime;
@@ -70,13 +70,14 @@
private final Context mContext;
- public LightBarTransitionsController(Context context, DarkIntensityApplier applier) {
+ public LightBarTransitionsController(Context context, DarkIntensityApplier applier,
+ CommandQueue commandQueue) {
mApplier = applier;
mHandler = new Handler();
mKeyguardStateController = Dependency.get(KeyguardStateController.class);
mStatusBarStateController = Dependency.get(StatusBarStateController.class);
- SysUiServiceProvider.getComponent(context, CommandQueue.class)
- .addCallback(this);
+ mCommandQueue = commandQueue;
+ mCommandQueue.addCallback(this);
mStatusBarStateController.addCallback(this);
mDozeAmount = mStatusBarStateController.getDozeAmount();
mContext = context;
@@ -84,8 +85,7 @@
}
public void destroy(Context context) {
- SysUiServiceProvider.getComponent(context, CommandQueue.class)
- .removeCallback(this);
+ mCommandQueue.removeCallback(this);
mStatusBarStateController.removeCallback(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
index fbd8d8a..07e9f94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
@@ -24,6 +24,8 @@
import android.os.UserHandle;
import android.os.UserManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@@ -40,6 +42,7 @@
private final Context mContext;
private final UserManager mUserManager;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private final LinkedList<UserInfo> mProfiles;
private boolean mListening;
private int mCurrentUser;
@@ -47,9 +50,10 @@
/**
*/
@Inject
- public ManagedProfileControllerImpl(Context context) {
+ public ManagedProfileControllerImpl(Context context, BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mUserManager = UserManager.get(mContext);
+ mBroadcastDispatcher = broadcastDispatcher;
mProfiles = new LinkedList<UserInfo>();
}
@@ -129,9 +133,10 @@
filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
- mContext.registerReceiverAsUser(mReceiver, UserHandle.ALL, filter, null, null);
+ mBroadcastDispatcher.registerReceiver(
+ mReceiver, filter, null /* handler */, UserHandle.ALL);
} else {
- mContext.unregisterReceiver(mReceiver);
+ mBroadcastDispatcher.unregisterReceiver(mReceiver);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 7030dfc..51b1bc7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -163,9 +163,9 @@
private int mDisabledFlags2;
private StatusBar mStatusBar;
private Recents mRecents;
- private Divider mDivider;
+ private final Divider mDivider;
private WindowManager mWindowManager;
- private CommandQueue mCommandQueue;
+ private final CommandQueue mCommandQueue;
private long mLastLockToAppLongPress;
private Locale mLocale;
@@ -265,7 +265,9 @@
NavigationModeController navigationModeController,
StatusBarStateController statusBarStateController,
SysUiState sysUiFlagsContainer,
- BroadcastDispatcher broadcastDispatcher) {
+ BroadcastDispatcher broadcastDispatcher,
+ CommandQueue commandQueue,
+ Divider divider) {
mAccessibilityManagerWrapper = accessibilityManagerWrapper;
mDeviceProvisionedController = deviceProvisionedController;
mStatusBarStateController = statusBarStateController;
@@ -277,6 +279,8 @@
mNavigationModeController = navigationModeController;
mNavBarMode = navigationModeController.addListener(this);
mBroadcastDispatcher = broadcastDispatcher;
+ mCommandQueue = commandQueue;
+ mDivider = divider;
}
// ----- Fragment Lifecycle Callbacks -----
@@ -284,11 +288,9 @@
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mCommandQueue = SysUiServiceProvider.getComponent(getContext(), CommandQueue.class);
mCommandQueue.observe(getLifecycle(), this);
mStatusBar = SysUiServiceProvider.getComponent(getContext(), StatusBar.class);
mRecents = SysUiServiceProvider.getComponent(getContext(), Recents.class);
- mDivider = SysUiServiceProvider.getComponent(getContext(), Divider.class);
mWindowManager = getContext().getSystemService(WindowManager.class);
mAccessibilityManager = getContext().getSystemService(AccessibilityManager.class);
mContentResolver = getContext().getContentResolver();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index 3b59031..1a6d3d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -34,6 +34,7 @@
import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.statusbar.CommandQueue;
import java.util.ArrayList;
import java.util.List;
@@ -78,12 +79,13 @@
}
};
- public NavigationBarTransitions(NavigationBarView view) {
+ public NavigationBarTransitions(NavigationBarView view, CommandQueue commandQueue) {
super(view, R.drawable.nav_background);
mView = view;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
- mLightTransitionsController = new LightBarTransitionsController(view.getContext(), this);
+ mLightTransitionsController = new LightBarTransitionsController(
+ view.getContext(), this, commandQueue);
mAllowAutoDimWallpaperNotVisible = view.getContext().getResources()
.getBoolean(R.bool.config_navigation_bar_enable_auto_dim_no_visible_wallpaper);
mDarkIntensityListeners = new ArrayList();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 4b4a35b..159a829 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -76,6 +76,7 @@
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.WindowManagerWrapper;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.policy.DeadZone;
import com.android.systemui.statusbar.policy.KeyButtonDrawable;
@@ -300,7 +301,7 @@
mConfiguration.updateFrom(context.getResources().getConfiguration());
mScreenPinningNotify = new ScreenPinningNotify(mContext);
- mBarTransitions = new NavigationBarTransitions(this);
+ mBarTransitions = new NavigationBarTransitions(this, Dependency.get(CommandQueue.class));
mButtonDispatchers.put(R.id.back, backButton);
mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
index 4f7af580..abceb11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationHandle.java
@@ -31,13 +31,13 @@
import com.android.systemui.R;
public class NavigationHandle extends View implements ButtonInterface {
- private float mDarkIntensity = -1;
private final Paint mPaint = new Paint();
private @ColorInt final int mLightColor;
private @ColorInt final int mDarkColor;
private final int mRadius;
private final int mBottom;
+ private boolean mRequiresInvalidate;
public NavigationHandle(Context context) {
this(context, null);
@@ -60,6 +60,15 @@
}
@Override
+ public void setAlpha(float alpha) {
+ super.setAlpha(alpha);
+ if (alpha > 0f && mRequiresInvalidate) {
+ mRequiresInvalidate = false;
+ invalidate();
+ }
+ }
+
+ @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
@@ -85,11 +94,15 @@
@Override
public void setDarkIntensity(float intensity) {
- if (mDarkIntensity != intensity) {
- mPaint.setColor((int) ArgbEvaluator.getInstance().evaluate(intensity, mLightColor,
- mDarkColor));
- mDarkIntensity = intensity;
- invalidate();
+ int color = (int) ArgbEvaluator.getInstance().evaluate(intensity, mLightColor, mDarkColor);
+ if (mPaint.getColor() != color) {
+ mPaint.setColor(color);
+ if (getVisibility() == VISIBLE && getAlpha() > 0) {
+ invalidate();
+ } else {
+ // If we are currently invisible, then invalidate when we are next made visible
+ mRequiresInvalidate = true;
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index e00cfb1..6839fb4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -16,7 +16,6 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.SysUiServiceProvider.getComponent;
import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator.ExpandAnimationParameters;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
@@ -109,6 +108,7 @@
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.util.InjectionInflationController;
+import com.android.systemui.util.Utils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -462,7 +462,7 @@
NotificationEntryManager notificationEntryManager,
KeyguardStateController keyguardStateController,
StatusBarStateController statusBarStateController, DozeLog dozeLog,
- DozeParameters dozeParameters) {
+ DozeParameters dozeParameters, CommandQueue commandQueue) {
super(context, attrs, falsingManager, dozeLog, keyguardStateController,
(SysuiStatusBarStateController) statusBarStateController);
setWillNotDraw(!DEBUG);
@@ -474,7 +474,7 @@
setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
mAlphaPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY));
setPanelAlpha(255, false /* animate */);
- mCommandQueue = getComponent(context, CommandQueue.class);
+ mCommandQueue = commandQueue;
mDisplayId = context.getDisplayId();
mPulseExpansionHandler = pulseExpansionHandler;
mDozeParameters = dozeParameters;
@@ -769,8 +769,7 @@
int sideMargin = res.getDimensionPixelOffset(R.dimen.notification_side_paddings);
int topMargin =
res.getDimensionPixelOffset(com.android.internal.R.dimen.quick_qs_total_height);
- int flag = Settings.System.getInt(mContext.getContentResolver(), "qs_media_player", 0);
- if (flag == 1) {
+ if (Utils.useQsMediaPlayer(mContext)) {
topMargin = res.getDimensionPixelOffset(
com.android.internal.R.dimen.quick_qs_total_height_with_media);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 294111c..01cd2b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -40,8 +40,8 @@
import com.android.internal.telephony.TelephonyIntents;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.UiOffloadThread;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.privacy.PrivacyItem;
import com.android.systemui.privacy.PrivacyItemController;
import com.android.systemui.privacy.PrivacyItemControllerKt;
@@ -138,7 +138,8 @@
private BluetoothController mBluetooth;
private AlarmManager.AlarmClockInfo mNextAlarm;
- public PhoneStatusBarPolicy(Context context, StatusBarIconController iconController) {
+ public PhoneStatusBarPolicy(Context context, StatusBarIconController iconController,
+ CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mIconController = iconController;
mCast = Dependency.get(CastController.class);
@@ -184,7 +185,7 @@
filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
- mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
+ broadcastDispatcher.registerReceiver(mIntentReceiver, filter, mHandler);
// listen for user / profile change.
try {
@@ -261,7 +262,7 @@
mSensorPrivacyController.addCallback(mSensorPrivacyListener);
mLocationController.addCallback(this);
- SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this);
+ commandQueue.addCallback(this);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 53e1467..312ca26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -19,7 +19,6 @@
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFromDirection;
-import static com.android.systemui.SysUiServiceProvider.getComponent;
import android.annotation.Nullable;
import android.content.Context;
@@ -95,7 +94,7 @@
super(context, attrs);
mBarTransitions = new PhoneStatusBarTransitions(this);
- mCommandQueue = getComponent(context, CommandQueue.class);
+ mCommandQueue = Dependency.get(CommandQueue.class);
}
public BarTransitions getBarTransitions() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 35039a0..f21a9a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -750,6 +750,11 @@
}
private void onFinished(Callback callback) {
+ if (mPendingFrameCallback != null) {
+ // No animations can finish while we're waiting on the blanking to finish
+ return;
+
+ }
if (isAnimating(mScrimBehind)
|| isAnimating(mScrimInFront)
|| isAnimating(mScrimForBubble)) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index afc147a..57dcf77b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -24,7 +24,6 @@
import static android.app.StatusBarManager.WindowVisibleState;
import static android.app.StatusBarManager.windowStateToString;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
-import static android.view.InsetsFlags.getAppearance;
import static android.view.InsetsState.TYPE_TOP_BAR;
import static android.view.InsetsState.containsType;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
@@ -75,7 +74,6 @@
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PointF;
import android.media.AudioAttributes;
@@ -100,6 +98,7 @@
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
@@ -108,7 +107,6 @@
import android.view.IWindowManager;
import android.view.InsetsState.InternalInsetType;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.RemoteAnimationAdapter;
import android.view.ThreadedRenderer;
@@ -167,7 +165,9 @@
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.OverlayPlugin;
import com.android.systemui.plugins.PluginDependencyProvider;
+import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -175,6 +175,7 @@
import com.android.systemui.qs.QSPanel;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
+import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.stackdivider.WindowManagerProxy;
@@ -197,6 +198,7 @@
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
@@ -233,11 +235,11 @@
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.util.InjectionInflationController;
import com.android.systemui.volume.VolumeComponent;
import java.io.FileDescriptor;
@@ -245,15 +247,13 @@
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Map;
+import java.util.Optional;
-import javax.inject.Inject;
import javax.inject.Named;
-import javax.inject.Singleton;
import dagger.Lazy;
import dagger.Subcomponent;
-@Singleton
public class StatusBar extends SystemUI implements DemoMode,
ActivityStarter, KeyguardStateController.Callback,
OnHeadsUpChangedListener, CommandQueue.Callbacks, ZenModeController.Callback,
@@ -358,8 +358,8 @@
private final Lazy<LockscreenWallpaper> mLockscreenWallpaperLazy;
protected LockscreenWallpaper mLockscreenWallpaper;
private final AutoHideController mAutoHideController;
-
- private int mNaturalBarHeight = -1;
+ @Nullable
+ private final KeyguardLiftController mKeyguardLiftController;
private final Point mCurrentDisplaySize = new Point();
@@ -379,7 +379,6 @@
private final FeatureFlags mFeatureFlags;
private final StatusBarIconController mIconController;
private final DozeLog mDozeLog;
- private final InjectionInflationController mInjectionInflater;
private final PulseExpansionHandler mPulseExpansionHandler;
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
private final KeyguardBypassController mKeyguardBypassController;
@@ -396,6 +395,10 @@
private final NotifLog mNotifLog;
private final DozeParameters mDozeParameters;
private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
+ private final PluginManager mPluginManager;
+ private final RemoteInputUriController mRemoteInputUriController;
+ private final Optional<Divider> mDividerOptional;
+ private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
// expanded notifications
protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -626,7 +629,13 @@
AppOpsManager.OP_COARSE_LOCATION,
AppOpsManager.OP_FINE_LOCATION};
- @Inject
+ /**
+ * Public constructor for StatusBar.
+ *
+ * StatusBar is considered optional, and therefore can not be marked as @Inject directly.
+ * Instead, an @Provide method is included.
+ */
+ @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
public StatusBar(
Context context,
FeatureFlags featureFlags,
@@ -635,7 +644,6 @@
KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarIconController statusBarIconController,
DozeLog dozeLog,
- InjectionInflationController injectionInflationController,
PulseExpansionHandler pulseExpansionHandler,
NotificationWakeUpCoordinator notificationWakeUpCoordinator,
KeyguardBypassController keyguardBypassController,
@@ -686,11 +694,17 @@
NotifLog notifLog,
DozeParameters dozeParameters,
ScrimController scrimController,
+ @Nullable KeyguardLiftController keyguardLiftController,
Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
DozeServiceHost dozeServiceHost,
PowerManager powerManager,
- DozeScrimController dozeScrimController) {
+ DozeScrimController dozeScrimController,
+ CommandQueue commandQueue,
+ PluginManager pluginManager,
+ RemoteInputUriController remoteInputUriController,
+ Optional<Divider> dividerOptional,
+ SuperStatusBarViewFactory superStatusBarViewFactory) {
super(context);
mFeatureFlags = featureFlags;
mLightBarController = lightBarController;
@@ -698,7 +712,6 @@
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mIconController = statusBarIconController;
mDozeLog = dozeLog;
- mInjectionInflater = injectionInflationController;
mPulseExpansionHandler = pulseExpansionHandler;
mWakeUpCoordinator = notificationWakeUpCoordinator;
mKeyguardBypassController = keyguardBypassController;
@@ -751,9 +764,16 @@
mPowerManager = powerManager;
mDozeParameters = dozeParameters;
mScrimController = scrimController;
+ mKeyguardLiftController = keyguardLiftController;
mLockscreenWallpaperLazy = lockscreenWallpaperLazy;
mDozeScrimController = dozeScrimController;
mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
+ mCommandQueue = commandQueue;
+ mPluginManager = pluginManager;
+ mRemoteInputUriController = remoteInputUriController;
+ mDividerOptional = dividerOptional;
+
+ mSuperStatusBarViewFactory = superStatusBarViewFactory;
mBubbleExpandListener =
(isExpanding, key) -> {
@@ -814,7 +834,6 @@
mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
// Connect in to the status bar manager service
- mCommandQueue = getComponent(CommandQueue.class);
mCommandQueue.addCallback(this);
RegisterStatusBarResult result = null;
@@ -832,8 +851,8 @@
if (mWallpaperSupported) {
// Make sure we always have the most current wallpaper info.
IntentFilter wallpaperChangedFilter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
- mContext.registerReceiverAsUser(mWallpaperChangedReceiver, UserHandle.ALL,
- wallpaperChangedFilter, null /* broadcastPermission */, null /* scheduler */);
+ mBroadcastDispatcher.registerReceiver(mWallpaperChangedReceiver, wallpaperChangedFilter,
+ null /* handler */, UserHandle.ALL);
mWallpaperChangedReceiver.onReceive(mContext, null);
} else if (DEBUG) {
Log.v(TAG, "start(): no wallpaper service ");
@@ -842,19 +861,11 @@
// Set up the initial notification state. This needs to happen before CommandQueue.disable()
setUpPresenter();
- if ((result.mSystemUiVisibility & View.STATUS_BAR_TRANSIENT) != 0) {
+ if (containsType(result.mTransientBarTypes, TYPE_TOP_BAR)) {
showTransientUnchecked();
}
- final int fullscreenAppearance = getAppearance(result.mFullscreenStackSysUiVisibility);
- final int dockedAppearance = getAppearance(result.mDockedStackSysUiVisibility);
- final AppearanceRegion[] appearanceRegions = result.mDockedStackBounds.isEmpty()
- ? new AppearanceRegion[]{
- new AppearanceRegion(fullscreenAppearance, result.mFullscreenStackBounds)}
- : new AppearanceRegion[]{
- new AppearanceRegion(fullscreenAppearance, result.mFullscreenStackBounds),
- new AppearanceRegion(dockedAppearance, result.mDockedStackBounds)};
- onSystemBarAppearanceChanged(mDisplayId, getAppearance(result.mSystemUiVisibility),
- appearanceRegions, result.mNavbarColorManagedByIme);
+ onSystemBarAppearanceChanged(mDisplayId, result.mAppearance, result.mAppearanceRegions,
+ result.mNavbarColorManagedByIme);
mAppFullscreen = result.mAppFullscreen;
mAppImmersive = result.mAppImmersive;
@@ -874,7 +885,7 @@
"init: icons=%d disabled=0x%08x lights=0x%08x imeButton=0x%08x",
numIcons,
result.mDisabledFlags1,
- result.mSystemUiVisibility,
+ result.mAppearance,
result.mImeWindowVis));
}
@@ -897,7 +908,8 @@
// end old BaseStatusBar.start().
// Lastly, call to the icon policy to install/update all the icons.
- mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController);
+ mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController, mCommandQueue,
+ mBroadcastDispatcher);
mSignalPolicy = new StatusBarSignalPolicy(mContext, mIconController);
mKeyguardStateController.addCallback(this);
@@ -921,6 +933,50 @@
int disabledFlags2 = result.mDisabledFlags2;
Dependency.get(InitController.class).addPostInitTask(
() -> setUpDisableFlags(disabledFlags1, disabledFlags2));
+
+ mPluginManager.addPluginListener(
+ new PluginListener<OverlayPlugin>() {
+ private ArraySet<OverlayPlugin> mOverlays = new ArraySet<>();
+
+ @Override
+ public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
+ mMainThreadHandler.post(
+ () -> plugin.setup(getStatusBarWindow(), getNavigationBarView(),
+ new Callback(plugin), mDozeParameters));
+ }
+
+ @Override
+ public void onPluginDisconnected(OverlayPlugin plugin) {
+ mMainThreadHandler.post(() -> {
+ mOverlays.remove(plugin);
+ mStatusBarWindowController.setForcePluginOpen(mOverlays.size() != 0);
+ });
+ }
+
+ class Callback implements OverlayPlugin.Callback {
+ private final OverlayPlugin mPlugin;
+
+ Callback(OverlayPlugin plugin) {
+ mPlugin = plugin;
+ }
+
+ @Override
+ public void onHoldStatusBarOpenChange() {
+ if (mPlugin.holdStatusBarOpen()) {
+ mOverlays.add(mPlugin);
+ } else {
+ mOverlays.remove(mPlugin);
+ }
+ mMainThreadHandler.post(() -> {
+ mStatusBarWindowController
+ .setStateListener(b -> mOverlays.forEach(
+ o -> o.setCollapseDesired(b)));
+ mStatusBarWindowController
+ .setForcePluginOpen(mOverlays.size() != 0);
+ });
+ }
+ }
+ }, OverlayPlugin.class, true /* Allow multiple plugins */);
}
// ================================================================================
@@ -999,7 +1055,7 @@
mHeadsUpAppearanceController = new HeadsUpAppearanceController(
mNotificationIconAreaController, mHeadsUpManager, mStatusBarWindow,
mStatusBarStateController, mKeyguardBypassController,
- mKeyguardStateController, mWakeUpCoordinator);
+ mKeyguardStateController, mWakeUpCoordinator, mCommandQueue);
mHeadsUpAppearanceController.readFrom(oldController);
mStatusBarWindowViewController.setStatusBarView(mStatusBarView);
updateAreThereNotifications();
@@ -1205,7 +1261,7 @@
mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanel,
mHeadsUpManager, mStatusBarWindow, mStackScroller, mDozeScrimController,
mScrimController, mActivityLaunchAnimator, mDynamicPrivacyController,
- mNotificationAlertingManager, rowBinder, mKeyguardStateController);
+ mNotificationAlertingManager, rowBinder, mKeyguardStateController, mCommandQueue);
mNotificationListController =
new NotificationListController(
@@ -1236,6 +1292,8 @@
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
mEntryManager.setRowBinder(rowBinder);
+ mRemoteInputUriController.attach(mEntryManager);
+
rowBinder.setNotificationClicker(new NotificationClicker(
this, mBubbleController, mNotificationActivityStarter));
@@ -1303,10 +1361,7 @@
}
private void inflateShelf() {
- mNotificationShelf =
- (NotificationShelf) mInjectionInflater.injectable(
- LayoutInflater.from(mContext)).inflate(
- R.layout.status_bar_notification_shelf, mStackScroller, false);
+ mNotificationShelf = mSuperStatusBarViewFactory.getNotificationShelf(mStackScroller);
mNotificationShelf.setOnClickListener(mGoToLockedShadeListener);
}
@@ -1364,10 +1419,8 @@
}
protected void inflateStatusBarWindow(Context context) {
- mStatusBarWindow = (StatusBarWindowView) mInjectionInflater.injectable(
- LayoutInflater.from(context)).inflate(R.layout.super_status_bar, null);
+ mStatusBarWindow = mSuperStatusBarViewFactory.getStatusBarWindowView();
mStatusBarWindowViewController = mStatusBarWindowViewControllerBuilder
- .setStatusBarWindowView(mStatusBarWindow)
.setShadeController(this)
.build();
}
@@ -1405,12 +1458,7 @@
}
public int getStatusBarHeight() {
- if (mNaturalBarHeight < 0) {
- final Resources res = mContext.getResources();
- mNaturalBarHeight =
- res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
- }
- return mNaturalBarHeight;
+ return mStatusBarWindowController.getStatusBarHeight();
}
protected boolean toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) {
@@ -1428,8 +1476,8 @@
: SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
return mRecents.splitPrimaryTask(createMode, null, metricsDockAction);
} else {
- Divider divider = getComponent(Divider.class);
- if (divider != null) {
+ if (mDividerOptional.isPresent()) {
+ Divider divider = mDividerOptional.get();
if (divider.isMinimized() && !divider.isHomeStackResizable()) {
// Undocking from the minimized state is not supported
return false;
@@ -2515,10 +2563,6 @@
mDozeLog.dump(pw);
- if (mBiometricUnlockController != null) {
- mBiometricUnlockController.dump(pw);
- }
-
if (mKeyguardIndicationController != null) {
mKeyguardIndicationController.dump(fd, pw, args);
}
@@ -2572,14 +2616,6 @@
mLightBarController.dump(fd, pw, args);
}
- if (mKeyguardBypassController != null) {
- mKeyguardBypassController.dump(pw);
- }
-
- if (mKeyguardUpdateMonitor != null) {
- mKeyguardUpdateMonitor.dump(fd, pw, args);
- }
-
mFalsingManager.dump(pw);
FalsingLog.dump(pw);
@@ -2596,7 +2632,7 @@
public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
makeStatusBarView(result);
- mStatusBarWindowController.add(mStatusBarWindow, getStatusBarHeight());
+ mStatusBarWindowController.attach();
}
// called by makeStatusbar and also by PhoneStatusBarView
@@ -2874,7 +2910,7 @@
mQSPanel.updateResources();
}
- loadDimens();
+ mStatusBarWindowController.refreshStatusBarHeight();
if (mStatusBarView != null) {
mStatusBarView.updateResources();
@@ -2887,19 +2923,6 @@
}
}
- protected void loadDimens() {
- final Resources res = mContext.getResources();
-
- int oldBarHeight = mNaturalBarHeight;
- mNaturalBarHeight = res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
- if (mStatusBarWindowController != null && mNaturalBarHeight != oldBarHeight) {
- mStatusBarWindowController.setBarHeight(mNaturalBarHeight);
- }
-
- if (DEBUG) Log.v(TAG, "defineSlots");
- }
-
// Visibility reporting
protected void handleVisibleToUserChanged(boolean visibleToUser) {
@@ -3928,14 +3951,14 @@
@Override
public void appTransitionCancelled(int displayId) {
if (displayId == mDisplayId) {
- getComponent(Divider.class).onAppTransitionFinished();
+ mDividerOptional.ifPresent(Divider::onAppTransitionFinished);
}
}
@Override
public void appTransitionFinished(int displayId) {
if (displayId == mDisplayId) {
- getComponent(Divider.class).onAppTransitionFinished();
+ mDividerOptional.ifPresent(Divider::onAppTransitionFinished);
}
}
@@ -4087,7 +4110,7 @@
// Begin Extra BaseStatusBar methods.
- protected CommandQueue mCommandQueue;
+ protected final CommandQueue mCommandQueue;
protected IStatusBarService mBarService;
// all notifications
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 2e2ff1a..5daef24 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -40,6 +40,7 @@
import com.android.systemui.R;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarMobileView;
import com.android.systemui.statusbar.StatusBarWifiView;
@@ -96,8 +97,8 @@
private final DarkIconDispatcher mDarkIconDispatcher;
private int mIconHPadding;
- public DarkIconManager(LinearLayout linearLayout) {
- super(linearLayout);
+ public DarkIconManager(LinearLayout linearLayout, CommandQueue commandQueue) {
+ super(linearLayout, commandQueue);
mIconHPadding = mContext.getResources().getDimensionPixelSize(
R.dimen.status_bar_icon_padding);
mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
@@ -156,8 +157,8 @@
public static class TintedIconManager extends IconManager {
private int mColor;
- public TintedIconManager(ViewGroup group) {
- super(group);
+ public TintedIconManager(ViewGroup group, CommandQueue commandQueue) {
+ super(group, commandQueue);
}
@Override
@@ -203,14 +204,14 @@
private boolean mIsInDemoMode;
protected DemoStatusIcons mDemoStatusIcons;
- public IconManager(ViewGroup group) {
+ public IconManager(ViewGroup group, CommandQueue commandQueue) {
mGroup = group;
mContext = group.getContext();
mIconSize = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_icon_size);
DisableStateTracker tracker =
- new DisableStateTracker(DISABLE_NONE, DISABLE2_SYSTEM_ICONS);
+ new DisableStateTracker(DISABLE_NONE, DISABLE2_SYSTEM_ICONS, commandQueue);
mGroup.addOnAttachStateChangeListener(tracker);
if (mGroup.isAttachedToWindow()) {
// In case we miss the first onAttachedToWindow event
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index e0b1846..aa062eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -29,7 +29,6 @@
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusIconDisplayable;
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
@@ -70,7 +69,7 @@
private boolean mIsDark = false;
@Inject
- public StatusBarIconControllerImpl(Context context) {
+ public StatusBarIconControllerImpl(Context context, CommandQueue commandQueue) {
super(context.getResources().getStringArray(
com.android.internal.R.array.config_statusBarIcons));
Dependency.get(ConfigurationController.class).addCallback(this);
@@ -79,8 +78,7 @@
loadDimens();
- SysUiServiceProvider.getComponent(context, CommandQueue.class)
- .addCallback(this);
+ commandQueue.addCallback(this);
Dependency.get(TunerService.class).addTunable(this, ICON_BLACKLIST);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
new file mode 100644
index 0000000..9e0eb35
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.util.DisplayMetrics;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.UiOffloadThread;
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.doze.DozeLog;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationViewHierarchyManager;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.StatusBarDependenciesModule;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.NotificationAlertingManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.logging.NotifLog;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.ZenModeController;
+
+import java.util.Optional;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger Module providing {@link StatusBar}.
+ */
+@Module(includes = {StatusBarDependenciesModule.class})
+public class StatusBarModule {
+ /**
+ * Provides our instance of StatusBar which is considered optional.
+ */
+ @Provides
+ @Singleton
+ static StatusBar provideStatusBar(
+ Context context,
+ FeatureFlags featureFlags,
+ LightBarController lightBarController,
+ AutoHideController autoHideController,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ StatusBarIconController statusBarIconController,
+ DozeLog dozeLog,
+ PulseExpansionHandler pulseExpansionHandler,
+ NotificationWakeUpCoordinator notificationWakeUpCoordinator,
+ KeyguardBypassController keyguardBypassController,
+ KeyguardStateController keyguardStateController,
+ HeadsUpManagerPhone headsUpManagerPhone,
+ DynamicPrivacyController dynamicPrivacyController,
+ BypassHeadsUpNotifier bypassHeadsUpNotifier,
+ @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowNotificationLongPress,
+ Lazy<NewNotifPipeline> newNotifPipeline,
+ FalsingManager falsingManager,
+ BroadcastDispatcher broadcastDispatcher,
+ RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
+ NotificationGutsManager notificationGutsManager,
+ NotificationLogger notificationLogger,
+ NotificationEntryManager notificationEntryManager,
+ NotificationInterruptionStateProvider notificationInterruptionStateProvider,
+ NotificationViewHierarchyManager notificationViewHierarchyManager,
+ ForegroundServiceController foregroundServiceController,
+ AppOpsController appOpsController,
+ KeyguardViewMediator keyguardViewMediator,
+ ZenModeController zenModeController,
+ NotificationAlertingManager notificationAlertingManager,
+ DisplayMetrics displayMetrics,
+ MetricsLogger metricsLogger,
+ UiOffloadThread uiOffloadThread,
+ NotificationMediaManager notificationMediaManager,
+ NotificationLockscreenUserManager lockScreenUserManager,
+ NotificationRemoteInputManager remoteInputManager,
+ UserSwitcherController userSwitcherController,
+ NetworkController networkController,
+ BatteryController batteryController,
+ SysuiColorExtractor colorExtractor,
+ ScreenLifecycle screenLifecycle,
+ WakefulnessLifecycle wakefulnessLifecycle,
+ SysuiStatusBarStateController statusBarStateController,
+ VibratorHelper vibratorHelper,
+ BubbleController bubbleController,
+ NotificationGroupManager groupManager,
+ NotificationGroupAlertTransferHelper groupAlertTransferHelper,
+ VisualStabilityManager visualStabilityManager,
+ DeviceProvisionedController deviceProvisionedController,
+ NavigationBarController navigationBarController,
+ AssistManager assistManager,
+ NotificationListener notificationListener,
+ ConfigurationController configurationController,
+ StatusBarWindowController statusBarWindowController,
+ StatusBarWindowViewController.Builder statusBarWindowViewControllerBuilder,
+ NotifLog notifLog,
+ DozeParameters dozeParameters,
+ ScrimController scrimController,
+ @Nullable KeyguardLiftController keyguardLiftController,
+ Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
+ Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+ DozeServiceHost dozeServiceHost,
+ PowerManager powerManager,
+ DozeScrimController dozeScrimController,
+ CommandQueue commandQueue,
+ PluginManager pluginManager,
+ RemoteInputUriController remoteInputUriController,
+ Optional<Divider> dividerOptional,
+ SuperStatusBarViewFactory superStatusBarViewFactory) {
+ return new StatusBar(
+ context,
+ featureFlags,
+ lightBarController,
+ autoHideController,
+ keyguardUpdateMonitor,
+ statusBarIconController,
+ dozeLog,
+ pulseExpansionHandler,
+ notificationWakeUpCoordinator,
+ keyguardBypassController,
+ keyguardStateController,
+ headsUpManagerPhone,
+ dynamicPrivacyController,
+ bypassHeadsUpNotifier,
+ allowNotificationLongPress,
+ newNotifPipeline,
+ falsingManager,
+ broadcastDispatcher,
+ remoteInputQuickSettingsDisabler,
+ notificationGutsManager,
+ notificationLogger,
+ notificationEntryManager,
+ notificationInterruptionStateProvider,
+ notificationViewHierarchyManager,
+ foregroundServiceController,
+ appOpsController,
+ keyguardViewMediator,
+ zenModeController,
+ notificationAlertingManager,
+ displayMetrics,
+ metricsLogger,
+ uiOffloadThread,
+ notificationMediaManager,
+ lockScreenUserManager,
+ remoteInputManager,
+ userSwitcherController,
+ networkController,
+ batteryController,
+ colorExtractor,
+ screenLifecycle,
+ wakefulnessLifecycle,
+ statusBarStateController,
+ vibratorHelper,
+ bubbleController,
+ groupManager,
+ groupAlertTransferHelper,
+ visualStabilityManager,
+ deviceProvisionedController,
+ navigationBarController,
+ assistManager,
+ notificationListener,
+ configurationController,
+ statusBarWindowController,
+ statusBarWindowViewControllerBuilder,
+ notifLog,
+ dozeParameters,
+ scrimController,
+ keyguardLiftController,
+ lockscreenWallpaperLazy,
+ biometricUnlockControllerLazy,
+ dozeServiceHost,
+ powerManager,
+ dozeScrimController,
+ commandQueue,
+ pluginManager,
+ remoteInputUriController,
+ dividerOptional,
+ superStatusBarViewFactory);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index b01a8d4..02e5ebf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -14,7 +14,6 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.SysUiServiceProvider.getComponent;
import static com.android.systemui.statusbar.phone.StatusBar.CLOSE_PANEL_WHEN_EMPTIED;
import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
import static com.android.systemui.statusbar.phone.StatusBar.MULTIUSER_DEBUG;
@@ -139,13 +138,14 @@
DynamicPrivacyController dynamicPrivacyController,
NotificationAlertingManager notificationAlertingManager,
NotificationRowBinderImpl notificationRowBinder,
- KeyguardStateController keyguardStateController) {
+ KeyguardStateController keyguardStateController,
+ CommandQueue commandQueue) {
mContext = context;
mKeyguardStateController = keyguardStateController;
mNotificationPanel = panel;
mHeadsUpManager = headsUp;
mDynamicPrivacyController = dynamicPrivacyController;
- mCommandQueue = getComponent(context, CommandQueue.class);
+ mCommandQueue = commandQueue;
mAboveShelfObserver = new AboveShelfObserver(stackScroller);
mActivityLaunchAnimator = activityLaunchAnimator;
mAboveShelfObserver.setListener(statusBarWindow.findViewById(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 1def89b..b5a7847 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -16,7 +16,6 @@
import static android.content.Intent.ACTION_DEVICE_LOCKED_CHANGED;
-import static com.android.systemui.SysUiServiceProvider.getComponent;
import static com.android.systemui.statusbar.NotificationLockscreenUserManager.NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION;
import android.app.ActivityManager;
@@ -80,7 +79,8 @@
NotificationLockscreenUserManager notificationLockscreenUserManager,
KeyguardStateController keyguardStateController,
StatusBarStateController statusBarStateController,
- ActivityStarter activityStarter, ShadeController shadeController) {
+ ActivityStarter activityStarter, ShadeController shadeController,
+ CommandQueue commandQueue) {
mContext = context;
mContext.registerReceiverAsUser(mChallengeReceiver, UserHandle.ALL,
new IntentFilter(ACTION_DEVICE_LOCKED_CHANGED), null, null);
@@ -91,7 +91,7 @@
mActivityStarter = activityStarter;
mStatusBarStateController.addCallback(this);
mKeyguardManager = context.getSystemService(KeyguardManager.class);
- mCommandQueue = getComponent(context, CommandQueue.class);
+ mCommandQueue = commandQueue;
mCommandQueue.addCallback(this);
mActivityIntentHelper = new ActivityIntentHelper(mContext);
mGroupManager = groupManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index ca7a936..2ecceba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -41,11 +41,13 @@
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.MainResources;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.RemoteInputController.Callback;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -69,6 +71,7 @@
public class StatusBarWindowController implements Callback, Dumpable, ConfigurationListener {
private static final String TAG = "StatusBarWindowController";
+ private static final boolean DEBUG = false;
private final Context mContext;
private final WindowManager mWindowManager;
@@ -83,7 +86,7 @@
private LayoutParams mLp;
private boolean mHasTopUi;
private boolean mHasTopUiChanged;
- private int mBarHeight;
+ private int mBarHeight = -1;
private float mScreenBrightnessDoze;
private final State mCurrentState = new State();
private OtherwisedCollapsedListener mListener;
@@ -92,13 +95,17 @@
mCallbacks = Lists.newArrayList();
private final SysuiColorExtractor mColorExtractor;
+ private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+ private final Resources mResources;
@Inject
public StatusBarWindowController(Context context, WindowManager windowManager,
IActivityManager activityManager, DozeParameters dozeParameters,
StatusBarStateController statusBarStateController,
ConfigurationController configurationController,
- KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor) {
+ KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor,
+ SuperStatusBarViewFactory superStatusBarViewFactory,
+ @MainResources Resources resources) {
mContext = context;
mWindowManager = windowManager;
mActivityManager = activityManager;
@@ -108,6 +115,15 @@
mLpChanged = new LayoutParams();
mKeyguardBypassController = keyguardBypassController;
mColorExtractor = colorExtractor;
+ mSuperStatusBarViewFactory = superStatusBarViewFactory;
+ mStatusBarView = mSuperStatusBarViewFactory.getStatusBarWindowView();
+ mResources = resources;
+
+ if (mBarHeight < 0) {
+ mBarHeight = mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+ }
+
mLockScreenDisplayTimeout = context.getResources()
.getInteger(R.integer.config_lockScreenDisplayTimeout);
((SysuiStatusBarStateController) statusBarStateController)
@@ -149,20 +165,36 @@
|| res.getBoolean(R.bool.config_enableLockScreenRotation);
}
+ public int getStatusBarHeight() {
+ return mBarHeight;
+ }
+
+ /**
+ * Rereads the status_bar_height from configuration and reapplys the current state if the height
+ * is different.
+ */
+ public void refreshStatusBarHeight() {
+ int heightFromConfig = mResources.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+
+ if (mBarHeight != heightFromConfig) {
+ mBarHeight = heightFromConfig;
+ apply(mCurrentState);
+ }
+
+ if (DEBUG) Log.v(TAG, "defineSlots");
+ }
+
/**
* Adds the status bar view to the window manager.
- *
- * @param statusBarView The view to add.
- * @param barHeight The height of the status bar in collapsed state.
*/
- public void add(ViewGroup statusBarView, int barHeight) {
-
+ public void attach() {
// Now that the status bar window encompasses the sliding panel and its
// translucent backdrop, the entire thing is made TRANSLUCENT and is
// hardware-accelerated.
mLp = new LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
- barHeight,
+ mBarHeight,
LayoutParams.TYPE_STATUS_BAR,
LayoutParams.FLAG_NOT_FOCUSABLE
| LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
@@ -176,8 +208,6 @@
mLp.setTitle("StatusBar");
mLp.packageName = mContext.getPackageName();
mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
- mStatusBarView = statusBarView;
- mBarHeight = barHeight;
mWindowManager.addView(mStatusBarView, mLp);
mLpChanged.copyFrom(mLp);
onThemeChanged();
@@ -534,11 +564,6 @@
apply(mCurrentState);
}
- public void setBarHeight(int barHeight) {
- mBarHeight = barHeight;
- apply(mCurrentState);
- }
-
public void setForcePluginOpen(boolean forcePluginOpen) {
mCurrentState.forcePluginOpen = forcePluginOpen;
apply(mCurrentState);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
index fd3f9c8..f716443 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowViewController.java
@@ -39,9 +39,11 @@
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -94,7 +96,8 @@
KeyguardStateController keyguardStateController,
SysuiStatusBarStateController statusBarStateController,
DozeLog dozeLog,
- DozeParameters dozeParameters) {
+ DozeParameters dozeParameters,
+ CommandQueue commandQueue) {
mView = view;
mFalsingManager = falsingManager;
@@ -115,7 +118,8 @@
keyguardStateController,
statusBarStateController,
dozeLog,
- dozeParameters);
+ dozeParameters,
+ commandQueue);
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
notificationPanelView.setVisibility(View.INVISIBLE);
@@ -488,7 +492,9 @@
private final NotificationEntryManager mNotificationEntryManager;
private final DozeLog mDozeLog;
private final DozeParameters mDozeParameters;
- private StatusBarWindowView mView;
+ private final CommandQueue mCommandQueue;
+ private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+ private final StatusBarWindowView mView;
@Inject
public Builder(
@@ -505,7 +511,9 @@
KeyguardStateController keyguardStateController,
StatusBarStateController statusBarStateController,
DozeLog dozeLog,
- DozeParameters dozeParameters) {
+ DozeParameters dozeParameters,
+ CommandQueue commandQueue,
+ SuperStatusBarViewFactory superStatusBarViewFactory) {
mInjectionInflationController = injectionInflationController;
mCoordinator = coordinator;
mPulseExpansionHandler = pulseExpansionHandler;
@@ -520,14 +528,10 @@
mStatusBarStateController = (SysuiStatusBarStateController) statusBarStateController;
mDozeLog = dozeLog;
mDozeParameters = dozeParameters;
- }
+ mCommandQueue = commandQueue;
+ mSuperStatusBarViewFactory = superStatusBarViewFactory;
- /**
- * Provide {@link StatusBarWindowView} to attach this controller to.
- */
- public Builder setStatusBarWindowView(StatusBarWindowView view) {
- mView = view;
- return this;
+ mView = mSuperStatusBarViewFactory.getStatusBarWindowView();
}
/**
@@ -558,7 +562,8 @@
mKeyguardStateController,
mStatusBarStateController,
mDozeLog,
- mDozeParameters);
+ mDozeParameters,
+ mCommandQueue);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index 3fc9b44..f0f9420 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -34,6 +34,7 @@
import com.android.settingslib.fuelgauge.Estimate;
import com.android.settingslib.utils.PowerUtil;
import com.android.systemui.Dependency;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.power.EnhancedEstimates;
import java.io.FileDescriptor;
@@ -58,6 +59,7 @@
private static final int UPDATE_GRANULARITY_MSEC = 1000 * 60;
private final EnhancedEstimates mEstimates;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private final ArrayList<BatteryController.BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
private final ArrayList<EstimateFetchCompletion> mFetchCallbacks = new ArrayList<>();
private final PowerManager mPowerManager;
@@ -76,17 +78,20 @@
private boolean mFetchingEstimate = false;
@Inject
- public BatteryControllerImpl(Context context, EnhancedEstimates enhancedEstimates) {
- this(context, enhancedEstimates, context.getSystemService(PowerManager.class));
+ public BatteryControllerImpl(Context context, EnhancedEstimates enhancedEstimates,
+ BroadcastDispatcher broadcastDispatcher) {
+ this(context, enhancedEstimates, context.getSystemService(PowerManager.class),
+ broadcastDispatcher);
}
@VisibleForTesting
BatteryControllerImpl(Context context, EnhancedEstimates enhancedEstimates,
- PowerManager powerManager) {
+ PowerManager powerManager, BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mHandler = new Handler();
mPowerManager = powerManager;
mEstimates = enhancedEstimates;
+ mBroadcastDispatcher = broadcastDispatcher;
registerReceiver();
updatePowerSave();
@@ -99,7 +104,7 @@
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
filter.addAction(ACTION_LEVEL_TEST);
- mContext.registerReceiver(this, filter);
+ mBroadcastDispatcher.registerReceiver(this, filter);
}
@Override
@@ -306,7 +311,7 @@
public void dispatchDemoCommand(String command, Bundle args) {
if (!mDemoMode && command.equals(COMMAND_ENTER)) {
mDemoMode = true;
- mContext.unregisterReceiver(this);
+ mBroadcastDispatcher.unregisterReceiver(this);
} else if (mDemoMode && command.equals(COMMAND_EXIT)) {
mDemoMode = false;
registerReceiver();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index b331fc3..dba3b92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -16,8 +16,6 @@
package com.android.systemui.statusbar.policy;
-import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
-
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -45,7 +43,6 @@
import com.android.systemui.Dependency;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.R;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
@@ -63,9 +60,6 @@
import java.util.Locale;
import java.util.TimeZone;
-import javax.inject.Inject;
-import javax.inject.Named;
-
/**
* Digital clock for the status bar.
*/
@@ -81,6 +75,7 @@
private static final String VISIBILITY = "visibility";
private final CurrentUserTracker mCurrentUserTracker;
+ private final CommandQueue mCommandQueue;
private int mCurrentUserId;
private boolean mClockVisibleByPolicy = true;
@@ -116,18 +111,12 @@
private final BroadcastDispatcher mBroadcastDispatcher;
public Clock(Context context, AttributeSet attrs) {
- this(context, attrs, null);
+ this(context, attrs, 0);
}
- @Inject
- public Clock(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
- BroadcastDispatcher broadcastDispatcher) {
- this(context, attrs, 0, broadcastDispatcher);
- }
-
- public Clock(Context context, AttributeSet attrs, int defStyle,
- BroadcastDispatcher broadcastDispatcher) {
+ public Clock(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
+ mCommandQueue = Dependency.get(CommandQueue.class);
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.Clock,
@@ -139,13 +128,13 @@
} finally {
a.recycle();
}
- mCurrentUserTracker = new CurrentUserTracker(context) {
+ mBroadcastDispatcher = Dependency.get(BroadcastDispatcher.class);
+ mCurrentUserTracker = new CurrentUserTracker(mBroadcastDispatcher) {
@Override
public void onUserSwitched(int newUserId) {
mCurrentUserId = newUserId;
}
};
- mBroadcastDispatcher = broadcastDispatcher;
}
@Override
@@ -196,11 +185,11 @@
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
filter.addAction(Intent.ACTION_USER_SWITCHED);
- getContext().registerReceiverAsUser(mIntentReceiver, UserHandle.ALL, filter,
- null, Dependency.get(Dependency.TIME_TICK_HANDLER));
+ mBroadcastDispatcher.registerReceiver(mIntentReceiver, filter,
+ Dependency.get(Dependency.TIME_TICK_HANDLER), UserHandle.ALL);
Dependency.get(TunerService.class).addTunable(this, CLOCK_SECONDS,
StatusBarIconController.ICON_BLACKLIST);
- SysUiServiceProvider.getComponent(getContext(), CommandQueue.class).addCallback(this);
+ mCommandQueue.addCallback(this);
if (mShowDark) {
Dependency.get(DarkIconDispatcher.class).addDarkReceiver(this);
}
@@ -224,11 +213,10 @@
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mAttached) {
- getContext().unregisterReceiver(mIntentReceiver);
+ mBroadcastDispatcher.unregisterReceiver(mIntentReceiver);
mAttached = false;
Dependency.get(TunerService.class).removeTunable(this);
- SysUiServiceProvider.getComponent(getContext(), CommandQueue.class)
- .removeCallback(this);
+ mCommandQueue.removeCallback(this);
if (mShowDark) {
Dependency.get(DarkIconDispatcher.class).removeDarkReceiver(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index 74a30fa..d488767 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -29,6 +29,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import java.util.Date;
import java.util.Locale;
@@ -41,6 +42,7 @@
private DateFormat mDateFormat;
private String mLastText;
private String mDatePattern;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
@@ -75,6 +77,7 @@
if (mDatePattern == null) {
mDatePattern = getContext().getString(R.string.system_ui_date_pattern);
}
+ mBroadcastDispatcher = Dependency.get(BroadcastDispatcher.class);
}
@Override
@@ -86,7 +89,7 @@
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
filter.addAction(Intent.ACTION_LOCALE_CHANGED);
- getContext().registerReceiver(mIntentReceiver, filter, null,
+ mBroadcastDispatcher.registerReceiver(mIntentReceiver, filter,
Dependency.get(Dependency.TIME_TICK_HANDLER));
updateClock();
@@ -97,7 +100,7 @@
super.onDetachedFromWindow();
mDateFormat = null; // reload the locale next time
- getContext().unregisterReceiver(mIntentReceiver);
+ mBroadcastDispatcher.unregisterReceiver(mIntentReceiver);
}
protected void updateClock() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
index 0a40b3c..b6ffd58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
@@ -24,6 +24,7 @@
import android.provider.Settings.Secure;
import android.util.Log;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.settings.CurrentUserTracker;
@@ -49,8 +50,9 @@
/**
*/
@Inject
- public DeviceProvisionedControllerImpl(Context context, @MainHandler Handler mainHandler) {
- super(context);
+ public DeviceProvisionedControllerImpl(Context context, @MainHandler Handler mainHandler,
+ BroadcastDispatcher broadcastDispatcher) {
+ super(broadcastDispatcher);
mContext = context;
mContentResolver = context.getContentResolver();
mDeviceProvisionedUri = Global.getUriFor(Global.DEVICE_PROVISIONED);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index 5a97eed..3d51be7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -35,6 +35,7 @@
import androidx.annotation.VisibleForTesting;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.BgLooper;
import com.android.systemui.util.Utils;
@@ -57,6 +58,7 @@
private AppOpsManager mAppOpsManager;
private StatusBarManager mStatusBarManager;
+ private BroadcastDispatcher mBroadcastDispatcher;
private boolean mAreActiveLocationRequests;
@@ -65,14 +67,16 @@
private final H mHandler = new H();
@Inject
- public LocationControllerImpl(Context context, @BgLooper Looper bgLooper) {
+ public LocationControllerImpl(Context context, @BgLooper Looper bgLooper,
+ BroadcastDispatcher broadcastDispatcher) {
mContext = context;
+ mBroadcastDispatcher = broadcastDispatcher;
// Register to listen for changes in location settings.
IntentFilter filter = new IntentFilter();
filter.addAction(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
filter.addAction(LocationManager.MODE_CHANGED_ACTION);
- context.registerReceiverAsUser(this, UserHandle.ALL, filter, null, new Handler(bgLooper));
+ mBroadcastDispatcher.registerReceiver(this, filter, new Handler(bgLooper), UserHandle.ALL);
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
mStatusBarManager
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 5da7267..bae51b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -48,6 +48,7 @@
import java.io.PrintWriter;
import java.util.BitSet;
+import java.util.concurrent.Executor;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -103,7 +104,7 @@
mPhone = phone;
mDefaults = defaults;
mSubscriptionInfo = info;
- mPhoneStateListener = new MobilePhoneStateListener(receiverLooper);
+ mPhoneStateListener = new MobilePhoneStateListener((new Handler(receiverLooper))::post);
mNetworkNameSeparator = getStringIfExists(R.string.status_bar_network_name_separator);
mNetworkNameDefault = getStringIfExists(
com.android.internal.R.string.lockscreen_carrier_default);
@@ -665,8 +666,8 @@
}
class MobilePhoneStateListener extends PhoneStateListener {
- public MobilePhoneStateListener(Looper looper) {
- super(looper);
+ public MobilePhoneStateListener(Executor executor) {
+ super(executor);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 60784c9..12d3577 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -64,6 +64,7 @@
import com.android.systemui.DemoMode;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.BgLooper;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
@@ -109,6 +110,7 @@
private final SubscriptionDefaults mSubDefaults;
private final DataSaverController mDataSaverController;
private final CurrentUserTracker mUserTracker;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private final Object mLock = new Object();
private Config mConfig;
@@ -170,7 +172,8 @@
*/
@Inject
public NetworkControllerImpl(Context context, @BgLooper Looper bgLooper,
- DeviceProvisionedController deviceProvisionedController) {
+ DeviceProvisionedController deviceProvisionedController,
+ BroadcastDispatcher broadcastDispatcher) {
this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),
(WifiManager) context.getSystemService(Context.WIFI_SERVICE),
@@ -179,7 +182,8 @@
new AccessPointControllerImpl(context),
new DataUsageController(context),
new SubscriptionDefaults(),
- deviceProvisionedController);
+ deviceProvisionedController,
+ broadcastDispatcher);
mReceiverHandler.post(mRegisterListeners);
}
@@ -191,12 +195,14 @@
AccessPointControllerImpl accessPointController,
DataUsageController dataUsageController,
SubscriptionDefaults defaultsHandler,
- DeviceProvisionedController deviceProvisionedController) {
+ DeviceProvisionedController deviceProvisionedController,
+ BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mConfig = config;
mReceiverHandler = new Handler(bgLooper);
mCallbackHandler = callbackHandler;
mDataSaverController = new DataSaverControllerImpl(context);
+ mBroadcastDispatcher = broadcastDispatcher;
mSubscriptionManager = subManager;
mSubDefaults = defaultsHandler;
@@ -229,7 +235,7 @@
// AIRPLANE_MODE_CHANGED is sent at boot; we've probably already missed it
updateAirplaneMode(true /* force callback */);
- mUserTracker = new CurrentUserTracker(mContext) {
+ mUserTracker = new CurrentUserTracker(broadcastDispatcher) {
@Override
public void onUserSwitched(int newUserId) {
NetworkControllerImpl.this.onUserSwitched(newUserId);
@@ -276,7 +282,7 @@
// exclusively for status bar icons.
mConnectivityManager.registerDefaultNetworkCallback(callback, mReceiverHandler);
// Register the listener on our bg looper
- mPhoneStateListener = new PhoneStateListener(bgLooper) {
+ mPhoneStateListener = new PhoneStateListener(mReceiverHandler::post) {
@Override
public void onActiveDataSubscriptionIdChanged(int subId) {
mActiveMobileDataSubscription = subId;
@@ -315,7 +321,7 @@
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
filter.addAction(Intent.ACTION_BOOT_COMPLETED);
filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
- mContext.registerReceiver(this, filter, null, mReceiverHandler);
+ mBroadcastDispatcher.registerReceiver(this, filter, mReceiverHandler);
mListening = true;
updateMobileControllers();
@@ -643,7 +649,7 @@
}
private boolean hasAnySim() {
- int simCount = mPhone.getSimCount();
+ int simCount = mPhone.getActiveModemCount();
for (int i = 0; i < simCount; i++) {
int state = mPhone.getSimState(i);
if (state != TelephonyManager.SIM_STATE_ABSENT
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java
index 2b60274..7ef9945 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.java
@@ -21,7 +21,6 @@
import android.content.res.Configuration;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -40,13 +39,13 @@
@VisibleForTesting boolean mRemoteInputActive;
@VisibleForTesting boolean misLandscape;
private int mLastOrientation;
- @VisibleForTesting CommandQueue mCommandQueue;
+ private final CommandQueue mCommandQueue;
@Inject
public RemoteInputQuickSettingsDisabler(Context context,
- ConfigurationController configController) {
+ ConfigurationController configController, CommandQueue commandQueue) {
mContext = context;
- mCommandQueue = SysUiServiceProvider.getComponent(context, CommandQueue.class);
+ mCommandQueue = commandQueue;
mLastOrientation = mContext.getResources().getConfiguration().orientation;
configController.addCallback(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputUriController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputUriController.java
new file mode 100644
index 0000000..4d912de
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputUriController.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy;
+
+import android.net.Uri;
+import android.os.RemoteException;
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Handles granting and revoking inline URI grants associated with RemoteInputs.
+ */
+@Singleton
+public class RemoteInputUriController {
+
+ private final IStatusBarService mStatusBarManagerService;
+ private static final String TAG = "RemoteInputUriController";
+
+ @Inject
+ public RemoteInputUriController(IStatusBarService statusBarService) {
+ mStatusBarManagerService = statusBarService;
+ }
+
+ /**
+ * Attach this controller as a listener to the provided NotificationEntryManager to ensure
+ * that RemoteInput URI grants are cleaned up when the notification entry is removed from
+ * the shade.
+ */
+ public void attach(NotificationEntryManager manager) {
+ manager.addNotificationEntryListener(mInlineUriListener);
+ }
+
+ /**
+ * Create a temporary grant which allows the app that submitted the notification access to the
+ * specified URI.
+ */
+ public void grantInlineReplyUriPermission(StatusBarNotification sbn, Uri data) {
+ try {
+ mStatusBarManagerService.grantInlineReplyUriPermission(
+ sbn.getKey(), data, sbn.getUser(), sbn.getPackageName());
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to grant URI permissions:" + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Ensures that inline URI permissions are cleared when notification entries are removed from
+ * the shade.
+ */
+ private final NotificationEntryListener mInlineUriListener = new NotificationEntryListener() {
+ @Override
+ public void onEntryRemoved(NotificationEntry entry, NotificationVisibility visibility,
+ boolean removedByUser) {
+ try {
+ mStatusBarManagerService.clearInlineReplyUriPermissions(entry.getKey());
+ } catch (RemoteException ex) {
+ ex.rethrowFromSystemServer();
+ }
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 502a9bd..307e3bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -173,12 +173,7 @@
protected Intent prepareRemoteInputFromData(String contentType, Uri data) {
HashMap<String, Uri> results = new HashMap<>();
results.put(contentType, data);
- try {
- mStatusBarManagerService.grantInlineReplyUriPermission(
- mEntry.getSbn().getKey(), data);
- } catch (Exception e) {
- Log.e(TAG, "Failed to grant URI permissions:" + e.getMessage(), e);
- }
+ mController.grantInlineReplyUriPermission(mEntry.getSbn(), data);
Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
RemoteInput.addDataResultToIntent(mRemoteInput, fillInIntent, results);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 0c68383..c161458 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -48,6 +48,7 @@
import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.BgHandler;
import com.android.systemui.settings.CurrentUserTracker;
@@ -100,13 +101,14 @@
/**
*/
@Inject
- public SecurityControllerImpl(Context context, @BgHandler Handler bgHandler) {
- this(context, bgHandler, null);
+ public SecurityControllerImpl(Context context, @BgHandler Handler bgHandler,
+ BroadcastDispatcher broadcastDispatcher) {
+ this(context, bgHandler, broadcastDispatcher, null);
}
public SecurityControllerImpl(Context context, Handler bgHandler,
- SecurityControllerCallback callback) {
- super(context);
+ BroadcastDispatcher broadcastDispatcher, SecurityControllerCallback callback) {
+ super(broadcastDispatcher);
mContext = context;
mBgHandler = bgHandler;
mDevicePolicyManager = (DevicePolicyManager)
@@ -124,8 +126,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(KeyChain.ACTION_TRUST_STORE_CHANGED);
filter.addAction(Intent.ACTION_USER_UNLOCKED);
- context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null,
- bgHandler);
+ broadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, bgHandler, UserHandle.ALL);
// TODO: re-register network callback on user change.
mConnectivityManager.registerNetworkCallback(REQUEST, mNetworkCallback);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index 65bb28f..949ac4d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -22,6 +22,7 @@
import android.text.method.TransformationMethod;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -238,13 +239,15 @@
public List<Button> inflateSmartActions(Context packageContext,
@NonNull SmartActions smartActions, SmartReplyController smartReplyController,
NotificationEntry entry, HeadsUpManager headsUpManager, boolean delayOnClickListener) {
+ Context themedPackageContext = new ContextThemeWrapper(packageContext, mContext.getTheme());
List<Button> buttons = new ArrayList<>();
int numSmartActions = smartActions.actions.size();
for (int n = 0; n < numSmartActions; n++) {
Notification.Action action = smartActions.actions.get(n);
if (action.actionIntent != null) {
buttons.add(inflateActionButton(
- this, getContext(), packageContext, n, smartActions, smartReplyController,
+ this, getContext(), themedPackageContext, n, smartActions,
+ smartReplyController,
entry, headsUpManager, delayOnClickListener));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 2c99668..13c0db9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -59,6 +59,7 @@
import com.android.systemui.Prefs.Key;
import com.android.systemui.R;
import com.android.systemui.SystemUISecondaryUserService;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
@@ -96,6 +97,7 @@
private final KeyguardStateController mKeyguardStateController;
protected final Handler mHandler;
private final ActivityStarter mActivityStarter;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private ArrayList<UserRecord> mUsers = new ArrayList<>();
private Dialog mExitGuestDialog;
@@ -111,10 +113,12 @@
@Inject
public UserSwitcherController(Context context, KeyguardStateController keyguardStateController,
- @MainHandler Handler handler, ActivityStarter activityStarter) {
+ @MainHandler Handler handler, ActivityStarter activityStarter,
+ BroadcastDispatcher broadcastDispatcher) {
mContext = context;
+ mBroadcastDispatcher = broadcastDispatcher;
if (!UserManager.isGuestUserEphemeral()) {
- mGuestResumeSessionReceiver.register(context);
+ mGuestResumeSessionReceiver.register(mBroadcastDispatcher);
}
mKeyguardStateController = keyguardStateController;
mHandler = handler;
@@ -127,8 +131,8 @@
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(Intent.ACTION_USER_STOPPED);
filter.addAction(Intent.ACTION_USER_UNLOCKED);
- mContext.registerReceiverAsUser(mReceiver, UserHandle.SYSTEM, filter,
- null /* permission */, null /* scheduler */);
+ mBroadcastDispatcher.registerReceiver(
+ mReceiver, filter, null /* handler */, UserHandle.SYSTEM);
mSecondaryUserServiceIntent = new Intent(context, SystemUISecondaryUserService.class);
@@ -459,8 +463,11 @@
}
private void listenForCallState() {
- TelephonyManager.from(mContext).listen(mPhoneStateListener,
- PhoneStateListener.LISTEN_CALL_STATE);
+ final TelephonyManager tele =
+ (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
+ if (tele != null) {
+ tele.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
+ }
}
private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index 1c7a195..a2028e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -39,6 +39,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dumpable;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.qs.GlobalSetting;
import com.android.systemui.settings.CurrentUserTracker;
@@ -77,8 +78,9 @@
private NotificationManager.Policy mConsolidatedNotificationPolicy;
@Inject
- public ZenModeControllerImpl(Context context, @MainHandler Handler handler) {
- super(context);
+ public ZenModeControllerImpl(Context context, @MainHandler Handler handler,
+ BroadcastDispatcher broadcastDispatcher) {
+ super(broadcastDispatcher);
mContext = context;
mModeSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE) {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index c2ed7df..379cf1f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -24,6 +24,9 @@
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.CommandQueue;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Status bar implementation for "large screen" products that mostly present no on-screen nav.
@@ -34,10 +37,15 @@
* recording, discloses the responsible applications </li>
* </ul>
*/
+@Singleton
public class TvStatusBar extends SystemUI implements CommandQueue.Callbacks {
- public TvStatusBar(Context context) {
+ private final CommandQueue mCommandQueue;
+
+ @Inject
+ public TvStatusBar(Context context, CommandQueue commandQueue) {
super(context);
+ mCommandQueue = commandQueue;
}
@Override
@@ -46,10 +54,9 @@
final IStatusBarService barService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
- final CommandQueue commandQueue = getComponent(CommandQueue.class);
- commandQueue.addCallback(this);
+ mCommandQueue.addCallback(this);
try {
- barService.registerStatusBar(commandQueue);
+ barService.registerStatusBar(mCommandQueue);
} catch (RemoteException ex) {
// If the system process isn't there we're doomed anyway.
}
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 9a58a35..128bb21 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -36,6 +36,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.google.android.collect.Sets;
@@ -45,6 +46,9 @@
import java.util.Map;
import java.util.Set;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Controls the application of theme overlays across the system for all users.
* This service is responsible for:
@@ -54,15 +58,19 @@
* - Observing work profile changes and applying overlays from the primary user to their
* associated work profiles
*/
+@Singleton
public class ThemeOverlayController extends SystemUI {
private static final String TAG = "ThemeOverlayController";
private static final boolean DEBUG = false;
private ThemeOverlayManager mThemeManager;
private UserManager mUserManager;
+ private BroadcastDispatcher mBroadcastDispatcher;
- public ThemeOverlayController(Context context) {
+ @Inject
+ public ThemeOverlayController(Context context, BroadcastDispatcher broadcastDispatcher) {
super(context);
+ mBroadcastDispatcher = broadcastDispatcher;
}
@Override
@@ -78,13 +86,13 @@
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_USER_SWITCHED);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
- mContext.registerReceiverAsUser(new BroadcastReceiver() {
+ mBroadcastDispatcher.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (DEBUG) Log.d(TAG, "Updating overlays for user switch / profile added.");
updateThemeOverlays();
}
- }, UserHandle.ALL, filter, null, bgHandler);
+ }, filter, bgHandler, UserHandle.ALL);
mContext.getContentResolver().registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES),
false,
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 2d6027c..ce0032e 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -34,6 +34,7 @@
import com.android.internal.util.ArrayUtils;
import com.android.systemui.DejankUtils;
import com.android.systemui.DemoMode;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.MainHandler;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.settings.CurrentUserTracker;
@@ -82,7 +83,7 @@
*/
@Inject
public TunerServiceImpl(Context context, @MainHandler Handler mainHandler,
- LeakDetector leakDetector) {
+ LeakDetector leakDetector, BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mContentResolver = mContext.getContentResolver();
mLeakDetector = leakDetector;
@@ -95,7 +96,7 @@
}
mCurrentUser = ActivityManager.getCurrentUser();
- mUserTracker = new CurrentUserTracker(mContext) {
+ mUserTracker = new CurrentUserTracker(broadcastDispatcher) {
@Override
public void onUserSwitched(int newUserId) {
mCurrentUser = newUserId;
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
index 4d12cc9..2f13f39 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingActivity.java
@@ -42,6 +42,9 @@
import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+
+import javax.inject.Inject;
public class UsbDebuggingActivity extends AlertActivity
implements DialogInterface.OnClickListener {
@@ -49,12 +52,20 @@
private CheckBox mAlwaysAllow;
private UsbDisconnectedReceiver mDisconnectedReceiver;
+ private final BroadcastDispatcher mBroadcastDispatcher;
private String mKey;
+ @Inject
+ public UsbDebuggingActivity(BroadcastDispatcher broadcastDispatcher) {
+ super();
+ mBroadcastDispatcher = broadcastDispatcher;
+ }
+
@Override
public void onCreate(Bundle icicle) {
Window window = getWindow();
- window.addSystemFlags(WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ window.addSystemFlags(
+ WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
super.onCreate(icicle);
@@ -138,13 +149,13 @@
public void onStart() {
super.onStart();
IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_STATE);
- registerReceiver(mDisconnectedReceiver, filter);
+ mBroadcastDispatcher.registerReceiver(mDisconnectedReceiver, filter);
}
@Override
protected void onStop() {
if (mDisconnectedReceiver != null) {
- unregisterReceiver(mDisconnectedReceiver);
+ mBroadcastDispatcher.unregisterReceiver(mDisconnectedReceiver);
}
super.onStop();
}
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingSecondaryUserActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingSecondaryUserActivity.java
index bafd1f1..032b72e 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingSecondaryUserActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDebuggingSecondaryUserActivity.java
@@ -29,10 +29,19 @@
import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
import com.android.systemui.R;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+
+import javax.inject.Inject;
public class UsbDebuggingSecondaryUserActivity extends AlertActivity
implements DialogInterface.OnClickListener {
private UsbDisconnectedReceiver mDisconnectedReceiver;
+ private final BroadcastDispatcher mBroadcastDispatcher;
+
+ @Inject
+ public UsbDebuggingSecondaryUserActivity(BroadcastDispatcher broadcastDispatcher) {
+ mBroadcastDispatcher = broadcastDispatcher;
+ }
@Override
public void onCreate(Bundle icicle) {
@@ -74,13 +83,13 @@
super.onStart();
IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_STATE);
- registerReceiver(mDisconnectedReceiver, filter);
+ mBroadcastDispatcher.registerReceiver(mDisconnectedReceiver, filter);
}
@Override
protected void onStop() {
if (mDisconnectedReceiver != null) {
- unregisterReceiver(mDisconnectedReceiver);
+ mBroadcastDispatcher.unregisterReceiver(mDisconnectedReceiver);
}
super.onStop();
}
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
index 0b27327..2e30d32 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
@@ -87,8 +87,10 @@
}
mDevice = (UsbDevice)target.getParcelableExtra(UsbManager.EXTRA_DEVICE);
+ boolean hasAudioCapture = false;
if (mDevice != null) {
mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice);
+ hasAudioCapture = mDevice.getHasAudioCapture();
} else {
mAccessory = (UsbAccessory)target.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (mAccessory == null) {
@@ -119,6 +121,8 @@
}
}
}
+ getIntent().putExtra(
+ ResolverActivity.EXTRA_IS_AUDIO_CAPTURE_DEVICE, hasAudioCapture);
CharSequence title = getResources().getText(com.android.internal.R.string.chooseUsbActivity);
super.onCreate(savedInstanceState, target, title, null, rList, true);
diff --git a/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java b/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java
index d101ccb..e93e241 100644
--- a/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/util/EmergencyDialerConstants.java
@@ -21,11 +21,10 @@
* Please keep these constants being consistent with those in com.android.phone.EmergencyDialer.
*/
public class EmergencyDialerConstants {
- // Intent action for emergency dialer activity.
- public static final String ACTION_DIAL = "com.android.phone.EmergencyDialer.DIAL";
/**
- * Extra included in {@link #ACTION_DIAL} to indicate the entry type that user starts
+ * Extra included in {@link android.telecom.TelecomManager#createLaunchEmergencyDialerIntent}
+ * to indicate the entry type that user starts
* the emergency dialer.
*/
public static final String EXTRA_ENTRY_TYPE =
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index 5ed027d..60d7678 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -37,7 +37,6 @@
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.phone.LockIcon;
import com.android.systemui.statusbar.phone.NotificationPanelView;
-import com.android.systemui.statusbar.policy.Clock;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -179,11 +178,6 @@
* Creates the QSCustomizer.
*/
QSCustomizer createQSCustomizer();
-
- /**
- * Creates a Clock.
- */
- Clock createClock();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java
index 92a8d84..47454cb 100644
--- a/packages/SystemUI/src/com/android/systemui/util/Utils.java
+++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java
@@ -20,9 +20,9 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.provider.Settings;
import android.view.View;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
@@ -52,25 +52,25 @@
View.OnAttachStateChangeListener {
private final int mMask1;
private final int mMask2;
+ private final CommandQueue mCommandQueue;
private View mView;
private boolean mDisabled;
- public DisableStateTracker(int disableMask, int disable2Mask) {
+ public DisableStateTracker(int disableMask, int disable2Mask, CommandQueue commandQueue) {
mMask1 = disableMask;
mMask2 = disable2Mask;
+ mCommandQueue = commandQueue;
}
@Override
public void onViewAttachedToWindow(View v) {
mView = v;
- SysUiServiceProvider.getComponent(v.getContext(), CommandQueue.class)
- .addCallback(this);
+ mCommandQueue.addCallback(this);
}
@Override
public void onViewDetachedFromWindow(View v) {
- SysUiServiceProvider.getComponent(mView.getContext(), CommandQueue.class)
- .removeCallback(this);
+ mCommandQueue.removeCallback(this);
mView = null;
}
@@ -124,4 +124,13 @@
&& QuickStepContract.isGesturalMode(navMode);
}
+ /**
+ * Allow the media player to be shown in the QS area, controlled by 2 flags.
+ */
+ public static boolean useQsMediaPlayer(Context context) {
+ int flag = Settings.System.getInt(context.getContentResolver(), "qs_media_player", 0);
+ flag |= Settings.System.getInt(context.getContentResolver(), "npv_plugin_flag", 0);
+
+ return flag > 0;
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index 1dd4863..d8eaaa1 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -145,6 +145,7 @@
mCarrierTextCallbackInfo = new CarrierTextController.CarrierTextCallbackInfo("",
new CharSequence[]{}, false, new int[]{});
when(mTelephonyManager.getSupportedModemCount()).thenReturn(3);
+ when(mTelephonyManager.getActiveModemCount()).thenReturn(3);
mCarrierTextController = new CarrierTextController(mContext, SEPARATOR, true, true);
// This should not start listening on any of the real dependencies but will test that
@@ -216,6 +217,15 @@
// There's only one subscription in the list
assertEquals(1, captor.getValue().listOfCarriers.length);
assertEquals(TEST_CARRIER, captor.getValue().listOfCarriers[0]);
+
+ // Now it becomes single SIM active mode.
+ reset(mCarrierTextCallback);
+ when(mTelephonyManager.getActiveModemCount()).thenReturn(1);
+ // Update carrier text. It should ignore error state of subId 3 in inactive slotId.
+ mCarrierTextController.updateCarrierText();
+ mTestableLooper.processAllMessages();
+ verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
+ assertEquals("TEST_CARRIER", captor.getValue().carrierText);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 57b0987..c1da53b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -26,6 +26,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
@@ -37,6 +38,7 @@
import android.app.trust.TrustManager;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricSourceType;
@@ -44,6 +46,8 @@
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.UserHandle;
import android.os.UserManager;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
@@ -56,7 +60,9 @@
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.systemui.DumpController;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import org.junit.Assert;
@@ -87,6 +93,8 @@
DATA_ROAMING_DISABLE, null, null, null, null, false, null, "", true, TEST_GROUP_UUID,
TEST_CARRIER_ID, 0);
@Mock
+ private DumpController mDumpController;
+ @Mock
private KeyguardUpdateMonitor.StrongAuthTracker mStrongAuthTracker;
@Mock
private TrustManager mTrustManager;
@@ -106,6 +114,8 @@
private KeyguardBypassController mKeyguardBypassController;
@Mock
private SubscriptionManager mSubscriptionManager;
+ @Mock
+ private BroadcastDispatcher mBroadcastDispatcher;
private TestableLooper mTestableLooper;
private TestableKeyguardUpdateMonitor mKeyguardUpdateMonitor;
@@ -140,6 +150,16 @@
}
@Test
+ public void testReceiversRegistered() {
+ verify(mBroadcastDispatcher, atLeastOnce()).registerReceiver(
+ eq(mKeyguardUpdateMonitor.mBroadcastReceiver),
+ any(IntentFilter.class), any(Handler.class));
+ verify(mBroadcastDispatcher, atLeastOnce()).registerReceiver(
+ eq(mKeyguardUpdateMonitor.mBroadcastAllReceiver),
+ any(IntentFilter.class), any(Handler.class), eq(UserHandle.ALL));
+ }
+
+ @Test
public void testIgnoresSimStateCallback_rebroadcast() {
Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
@@ -515,9 +535,9 @@
AtomicBoolean mSimStateChanged = new AtomicBoolean(false);
protected TestableKeyguardUpdateMonitor(Context context) {
- super(context, TestableLooper.get(KeyguardUpdateMonitorTest.this).getLooper());
- context.unregisterReceiver(mBroadcastReceiver);
- context.unregisterReceiver(mBroadcastAllReceiver);
+ super(context,
+ TestableLooper.get(KeyguardUpdateMonitorTest.this).getLooper(),
+ mBroadcastDispatcher, mDumpController);
mStrongAuthTracker = KeyguardUpdateMonitorTest.this.mStrongAuthTracker;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java
index 939df10..c020514 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java
@@ -30,6 +30,7 @@
import org.junit.Assert;
import org.junit.Test;
+import java.io.FileDescriptor;
import java.io.PrintWriter;
@SmallTest
@@ -56,10 +57,12 @@
@Test
public void testDump() {
Dumpable d = mock(Dumpable.class);
+ String[] args = new String[0];
+ FileDescriptor fd = mock(FileDescriptor.class);
mDependency.injectTestDependency(DUMPABLE, d);
Dependency.get(DUMPABLE);
- mDependency.dump(null, mock(PrintWriter.class), null);
- verify(d).dump(eq(null), any(), eq(null));
+ mDependency.dump(fd, mock(PrintWriter.class), args);
+ verify(d).dump(eq(fd), any(), eq(args));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index 7359fdce..1e9000b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -50,6 +50,7 @@
import com.android.systemui.R.dimen;
import com.android.systemui.ScreenDecorations.TunablePaddingTagListener;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -79,9 +80,13 @@
private WindowManager mWindowManager;
private FragmentService mFragmentService;
private FragmentHostManager mFragmentHostManager;
- private TunerService mTunerService;
private StatusBarWindowView mView;
private TunablePaddingService mTunablePaddingService;
+ private Handler mMainHandler;
+ @Mock
+ private TunerService mTunerService;
+ @Mock
+ private BroadcastDispatcher mBroadcastDispatcher;
@Mock private Lazy<StatusBar> mStatusBarLazy;
@Before
@@ -89,10 +94,8 @@
MockitoAnnotations.initMocks(this);
mTestableLooper = TestableLooper.get(this);
- mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
- new Handler(mTestableLooper.getLooper()));
+ mMainHandler = new Handler(mTestableLooper.getLooper());
mTunablePaddingService = mDependency.injectMockDependency(TunablePaddingService.class);
- mTunerService = mDependency.injectMockDependency(TunerService.class);
mFragmentService = mDependency.injectMockDependency(FragmentService.class);
mWindowManager = mock(WindowManager.class);
@@ -108,7 +111,8 @@
when(mFragmentService.getFragmentHostManager(any())).thenReturn(mFragmentHostManager);
- mScreenDecorations = new ScreenDecorations(mContext, mStatusBarLazy) {
+ mScreenDecorations = new ScreenDecorations(mContext, mStatusBarLazy, mMainHandler,
+ mBroadcastDispatcher, mTunerService) {
@Override
public void start() {
super.start();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SizeCompatModeActivityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/SizeCompatModeActivityControllerTest.java
index 06999bc..1638ea1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SizeCompatModeActivityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SizeCompatModeActivityControllerTest.java
@@ -31,6 +31,7 @@
import com.android.systemui.SizeCompatModeActivityController.RestartActivityButton;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
+import com.android.systemui.statusbar.CommandQueue;
import org.junit.Before;
import org.junit.Test;
@@ -58,7 +59,8 @@
MockitoAnnotations.initMocks(this);
doReturn(true).when(mMockButton).show();
- mController = new SizeCompatModeActivityController(mContext, mMockAm) {
+ mController = new SizeCompatModeActivityController(mContext, mMockAm,
+ new CommandQueue(mContext)) {
@Override
RestartActivityButton createRestartButton(Context context) {
return mMockButton;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java
index a766885..7d55623 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SliceBroadcastRelayHandlerTest.java
@@ -17,6 +17,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
@@ -34,11 +35,14 @@
import androidx.test.filters.SmallTest;
import com.android.settingslib.SliceBroadcastRelay;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@SmallTest
@@ -47,11 +51,15 @@
private static final String TEST_ACTION = "com.android.systemui.action.TEST_ACTION";
private SliceBroadcastRelayHandler mRelayHandler;
private Context mSpyContext;
+ @Mock
+ private BroadcastDispatcher mBroadcastDispatcher;
+
@Before
public void setup() {
+ MockitoAnnotations.initMocks(this);
mSpyContext = spy(mContext);
- mRelayHandler = new SliceBroadcastRelayHandler(mSpyContext);
+ mRelayHandler = new SliceBroadcastRelayHandler(mSpyContext, mBroadcastDispatcher);
}
@Test
@@ -136,6 +144,16 @@
verify(Receiver.sReceiver, timeout(2000)).onReceive(any(), any());
}
+ @Test
+ public void testRegisteredWithDispatcher() {
+ mRelayHandler.start();
+
+ verify(mBroadcastDispatcher)
+ .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
+ verify(mSpyContext, never())
+ .registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
+ }
+
public static class Receiver extends BroadcastReceiver {
private static BroadcastReceiver sReceiver;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index 85d818a..486fa12 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -35,6 +35,7 @@
import android.app.IActivityTaskManager;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.hardware.biometrics.Authenticator;
@@ -88,7 +89,6 @@
TestableContext context = spy(mContext);
mContext.putComponent(StatusBar.class, mock(StatusBar.class));
- mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
when(context.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE))
@@ -102,7 +102,8 @@
when(mDialog1.isAllowDeviceCredentials()).thenReturn(false);
when(mDialog2.isAllowDeviceCredentials()).thenReturn(false);
- mAuthController = new TestableAuthController(context, new MockInjector());
+ mAuthController = new TestableAuthController(
+ context, mock(CommandQueue.class), new MockInjector());
mAuthController.mComponents = mContext.getComponents();
mAuthController.start();
@@ -403,6 +404,19 @@
mAuthController.onDeviceCredentialPressed();
}
+ @Test
+ public void testActionCloseSystemDialogs_dismissesDialogIfShowing() throws Exception {
+ showDialog(Authenticator.TYPE_BIOMETRIC, BiometricPrompt.TYPE_FACE);
+ Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ mAuthController.mBroadcastReceiver.onReceive(mContext, intent);
+ waitForIdleSync();
+
+ assertNull(mAuthController.mCurrentDialog);
+ assertNull(mAuthController.mReceiver);
+ verify(mDialog1).dismissWithoutCallback(true /* animate */);
+ verify(mReceiver).onDialogDismissed(eq(BiometricPrompt.DISMISSED_REASON_USER_CANCEL));
+ }
+
// Helpers
private void showDialog(int authenticators, int biometricModality) {
@@ -435,8 +449,8 @@
private int mBuildCount = 0;
private Bundle mLastBiometricPromptBundle;
- TestableAuthController(Context context, Injector injector) {
- super(context, injector);
+ TestableAuthController(Context context, CommandQueue commandQueue, Injector injector) {
+ super(context, commandQueue, injector);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
index 2bff548..ead14e5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
@@ -21,6 +21,7 @@
import android.content.IntentFilter
import android.os.Handler
import android.os.Looper
+import android.os.PatternMatcher
import android.os.UserHandle
import android.test.suitebuilder.annotation.SmallTest
import android.testing.AndroidTestingRunner
@@ -33,6 +34,7 @@
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
+import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
@@ -48,6 +50,10 @@
val user1 = UserHandle.of(1)
fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
+ const val TEST_ACTION = "TEST_ACTION"
+ const val TEST_SCHEME = "TEST_SCHEME"
+ const val TEST_PATH = "TEST_PATH"
+ const val TEST_TYPE = "test/type"
}
@Mock
@@ -83,6 +89,11 @@
Handler(testableLooper.looper),
testableLooper.looper,
mapOf(0 to mockUBRUser0, 1 to mockUBRUser1))
+
+ // These should be valid filters
+ `when`(intentFilter.countActions()).thenReturn(1)
+ `when`(intentFilterOther.countActions()).thenReturn(1)
+ `when`(mockContext.user).thenReturn(user0)
}
@Test
@@ -129,6 +140,44 @@
verify(mockUBRUser1, never()).unregisterReceiver(broadcastReceiver)
}
+ @Test(expected = IllegalArgumentException::class)
+ fun testFilterMustContainActions() {
+ val testFilter = IntentFilter()
+ broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun testFilterMustNotContainDataScheme() {
+ val testFilter = IntentFilter(TEST_ACTION).apply {
+ addDataScheme(TEST_SCHEME)
+ }
+ broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun testFilterMustNotContainDataAuthority() {
+ val testFilter = IntentFilter(TEST_ACTION).apply {
+ addDataAuthority(mock(IntentFilter.AuthorityEntry::class.java))
+ }
+ broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun testFilterMustNotContainDataPath() {
+ val testFilter = IntentFilter(TEST_ACTION).apply {
+ addDataPath(TEST_PATH, PatternMatcher.PATTERN_LITERAL)
+ }
+ broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
+ }
+
+ @Test(expected = IllegalArgumentException::class)
+ fun testFilterMustNotContainDataType() {
+ val testFilter = IntentFilter(TEST_ACTION).apply {
+ addDataType(TEST_TYPE)
+ }
+ broadcastDispatcher.registerReceiver(broadcastReceiver, testFilter)
+ }
+
private class TestBroadcastDispatcher(
context: Context,
mainHandler: Handler,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index 0068113..b1a6bc6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -46,18 +46,19 @@
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Resources;
import android.graphics.drawable.Icon;
import android.hardware.face.FaceManager;
import android.service.notification.ZenModeConfig;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.WindowManager;
-import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
import com.android.internal.colorextraction.ColorExtractor;
import com.android.systemui.R;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -65,6 +66,7 @@
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -81,6 +83,7 @@
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.InjectionInflationController;
import org.junit.Before;
import org.junit.Test;
@@ -119,7 +122,6 @@
@Mock
private KeyguardBypassController mKeyguardBypassController;
- private FrameLayout mStatusBarView;
@Captor
private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
@Captor
@@ -147,22 +149,28 @@
private SysuiColorExtractor mColorExtractor;
@Mock
ColorExtractor.GradientColors mGradientColors;
+ @Mock
+ private Resources mResources;
+ private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
private BubbleData mBubbleData;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mStatusBarView = new FrameLayout(mContext);
mDependency.injectTestDependency(NotificationEntryManager.class, mNotificationEntryManager);
mContext.addMockSystemService(FaceManager.class, mFaceManager);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
+ mSuperStatusBarViewFactory = new SuperStatusBarViewFactory(mContext,
+ new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()));
+
// Bubbles get added to status bar window view
mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
mActivityManager, mDozeParameters, mStatusBarStateController,
- mConfigurationController, mKeyguardBypassController, mColorExtractor);
- mStatusBarWindowController.add(mStatusBarView, 120 /* height */);
+ mConfigurationController, mKeyguardBypassController, mColorExtractor,
+ mSuperStatusBarViewFactory, mResources);
+ mStatusBarWindowController.attach();
// Need notifications for bubbles
mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
index 316b891..2ed0b4f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
@@ -45,6 +45,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.util.sensors.FakeSensorManager;
import org.junit.Before;
@@ -66,6 +67,8 @@
FakeSensorManager mSensorManager;
@Mock
DozeHost mDozeHost;
+ @Mock
+ BroadcastDispatcher mBroadcastDispatcher;
DozeScreenBrightness mScreen;
@Before
@@ -82,7 +85,7 @@
mSensorManager = new FakeSensorManager(mContext);
mSensor = mSensorManager.getFakeLightSensor();
mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager,
- mSensor.getSensor(), mDozeHost, null /* handler */,
+ mSensor.getSensor(), mBroadcastDispatcher, mDozeHost, null /* handler */,
DEFAULT_BRIGHTNESS, SENSOR_TO_BRIGHTNESS, SENSOR_TO_OPACITY,
true /* debuggable */);
}
@@ -185,7 +188,7 @@
@Test
public void testNullSensor() throws Exception {
mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager,
- null /* sensor */, mDozeHost, null /* handler */,
+ null /* sensor */, mBroadcastDispatcher, mDozeHost, null /* handler */,
DEFAULT_BRIGHTNESS, SENSOR_TO_BRIGHTNESS, SENSOR_TO_OPACITY,
true /* debuggable */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 756227e..226bf6b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -39,6 +39,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dock.DockManager;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.sensors.AsyncSensorManager;
@@ -66,6 +67,8 @@
private DozeHost mHost;
@Mock
private AlarmManager mAlarmManager;
+ @Mock
+ private BroadcastDispatcher mBroadcastDispatcher;
private DozeTriggers mTriggers;
private FakeSensorManager mSensors;
private Sensor mTapSensor;
@@ -87,7 +90,7 @@
mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager, config, parameters,
asyncSensorManager, Handler.createAsync(Looper.myLooper()), wakeLock, true,
- mDockManagerFake, mProximitySensor, mock(DozeLog.class));
+ mDockManagerFake, mProximitySensor, mock(DozeLog.class), mBroadcastDispatcher);
waitForSensorManager();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 9312ed2..c815279 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -37,6 +37,7 @@
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -60,6 +61,7 @@
private @Mock StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private @Mock StatusBarWindowController mStatusBarWindowController;
private @Mock SystemUIFactory mSystemUIFactory;
+ private @Mock BroadcastDispatcher mBroadcastDispatcher;
private FalsingManagerFake mFalsingManager;
@@ -81,7 +83,8 @@
TestableLooper.get(this).runWithLooper(() -> {
mViewMediator = new KeyguardViewMediator(
- mContext, mFalsingManager, mLockPatternUtils, mSystemUIFactory);
+ mContext, mFalsingManager, mLockPatternUtils, mBroadcastDispatcher,
+ mSystemUIFactory);
});
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java
index 6e726cf..e4c387a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityTest.java
@@ -19,7 +19,10 @@
import static android.app.ActivityManager.TaskDescription;
import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.annotation.ColorInt;
@@ -35,7 +38,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.keyguard.WorkLockActivity;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import org.junit.Before;
import org.junit.Test;
@@ -55,12 +58,13 @@
private @Mock DevicePolicyManager mDevicePolicyManager;
private @Mock KeyguardManager mKeyguardManager;
private @Mock Context mContext;
+ private @Mock BroadcastDispatcher mBroadcastDispatcher;
private WorkLockActivity mActivity;
private static class WorkLockActivityTestable extends WorkLockActivity {
- WorkLockActivityTestable(Context baseContext) {
- super();
+ WorkLockActivityTestable(Context baseContext, BroadcastDispatcher broadcastDispatcher) {
+ super(broadcastDispatcher);
attachBaseContext(baseContext);
}
}
@@ -77,7 +81,7 @@
if (Looper.myLooper() == null) {
Looper.prepare();
}
- mActivity = new WorkLockActivityTestable(mContext);
+ mActivity = new WorkLockActivityTestable(mContext, mBroadcastDispatcher);
}
@Test
@@ -110,4 +114,11 @@
.putExtra(Intent.EXTRA_USER_ID, USER_ID));
assertEquals(orgColor, mActivity.getPrimaryColor());
}
+
+ @Test
+ public void testUnregisteredFromDispatcher() {
+ mActivity.unregisterBroadcastReceiver();
+ verify(mBroadcastDispatcher).unregisterReceiver(any());
+ verify(mContext, never()).unregisterReceiver(any());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
index 462c82e..098521f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
@@ -36,6 +36,7 @@
import com.android.systemui.SysuiTestCase
import com.android.systemui.appops.AppOpItem
import com.android.systemui.appops.AppOpsController
+import com.android.systemui.broadcast.BroadcastDispatcher
import org.hamcrest.Matchers.hasItem
import org.hamcrest.Matchers.not
import org.hamcrest.Matchers.nullValue
@@ -62,7 +63,6 @@
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
-import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.MockitoAnnotations
@@ -89,6 +89,8 @@
private lateinit var callback: PrivacyItemController.Callback
@Mock
private lateinit var userManager: UserManager
+ @Mock
+ private lateinit var broadcastDispatcher: BroadcastDispatcher
@Captor
private lateinit var argCaptor: ArgumentCaptor<List<PrivacyItem>>
@Captor
@@ -99,7 +101,7 @@
private lateinit var handler: Handler
fun PrivacyItemController(context: Context) =
- PrivacyItemController(context, appOpsController, handler, handler)
+ PrivacyItemController(context, appOpsController, handler, handler, broadcastDispatcher)
@Before
fun setup() {
@@ -180,14 +182,12 @@
@Test
fun testRegisterReceiver_allUsers() {
- val spiedContext = spy(mContext)
- val itemController = PrivacyItemController(spiedContext)
- itemController.addCallback(callback)
+ privacyItemController.addCallback(callback)
testableLooper.processAllMessages()
- verify(spiedContext, atLeastOnce()).registerReceiverAsUser(
- eq(itemController.userSwitcherReceiver), eq(UserHandle.ALL), any(), eq(null),
- eq(null))
- verify(spiedContext, never()).unregisterReceiver(eq(itemController.userSwitcherReceiver))
+ verify(broadcastDispatcher, atLeastOnce()).registerReceiver(
+ eq(privacyItemController.userSwitcherReceiver), any(), eq(null), eq(UserHandle.ALL))
+ verify(broadcastDispatcher, never())
+ .unregisterReceiver(eq(privacyItemController.userSwitcherReceiver))
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 4eee230..a31fc3a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -39,9 +39,11 @@
import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiBaseFragmentTest;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.AutoTileManager;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.policy.Clock;
@@ -97,7 +99,8 @@
QSTileHost host = new QSTileHost(mContext, mock(StatusBarIconController.class),
mock(QSFactoryImpl.class), new Handler(), Looper.myLooper(),
mock(PluginManager.class), mock(TunerService.class),
- () -> mock(AutoTileManager.class), mock(DumpController.class));
+ () -> mock(AutoTileManager.class), mock(DumpController.class),
+ mock(BroadcastDispatcher.class));
qs.setHost(host);
qs.setListening(true);
@@ -136,11 +139,14 @@
@Override
protected Fragment instantiate(Context context, String className, Bundle arguments) {
+ CommandQueue commandQueue = new CommandQueue(context);
return new QSFragment(
- new RemoteInputQuickSettingsDisabler(context, mock(ConfigurationController.class)),
+ new RemoteInputQuickSettingsDisabler(context, mock(ConfigurationController.class),
+ commandQueue),
new InjectionInflationController(SystemUIFactory.getInstance().getRootComponent()),
context,
mock(QSTileHost.class),
- mock(StatusBarStateController.class));
+ mock(StatusBarStateController.class),
+ commandQueue);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index 7752014..0247c2f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -41,6 +41,7 @@
import com.android.systemui.DumpController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
@@ -84,6 +85,8 @@
@Mock
private DumpController mDumpController;
@Mock
+ private BroadcastDispatcher mBroadcastDispatcher;
+ @Mock
private QSTile.State mMockState;
private Handler mHandler;
private TestableLooper mLooper;
@@ -96,7 +99,7 @@
mHandler = new Handler(mLooper.getLooper());
mQSTileHost = new TestQSTileHost(mContext, mIconController, mDefaultFactory, mHandler,
mLooper.getLooper(),
- mPluginManager, mTunerService, mAutoTiles, mDumpController);
+ mPluginManager, mTunerService, mAutoTiles, mDumpController, mBroadcastDispatcher);
setUpTileFactory();
Settings.Secure.putStringForUser(mContext.getContentResolver(), QSTileHost.TILES_SETTING,
"", ActivityManager.getCurrentUser());
@@ -168,9 +171,10 @@
TestQSTileHost(Context context, StatusBarIconController iconController,
QSFactoryImpl defaultFactory, Handler mainHandler, Looper bgLooper,
PluginManager pluginManager, TunerService tunerService,
- Provider<AutoTileManager> autoTiles, DumpController dumpController) {
+ Provider<AutoTileManager> autoTiles, DumpController dumpController,
+ BroadcastDispatcher broadcastDispatcher) {
super(context, iconController, defaultFactory, mainHandler, bgLooper, pluginManager,
- tunerService, autoTiles, dumpController);
+ tunerService, autoTiles, dumpController, broadcastDispatcher);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
index 11b0c69..9e5e582 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileLifecycleManagerTest.java
@@ -45,6 +45,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import org.junit.After;
import org.junit.Before;
@@ -59,6 +60,8 @@
private final PackageManagerAdapter mMockPackageManagerAdapter =
Mockito.mock(PackageManagerAdapter.class);
+ private final BroadcastDispatcher mMockBroadcastDispatcher =
+ Mockito.mock(BroadcastDispatcher.class);
private final IQSTileService.Stub mMockTileService = Mockito.mock(IQSTileService.Stub.class);
private ComponentName mTileServiceComponentName;
private Intent mTileServiceIntent;
@@ -87,7 +90,8 @@
Mockito.mock(IQSService.class), new Tile(),
mTileServiceIntent,
mUser,
- mMockPackageManagerAdapter);
+ mMockPackageManagerAdapter,
+ mMockBroadcastDispatcher);
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index d18cebb..824c50d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -32,6 +32,7 @@
import com.android.systemui.DumpController;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.shared.plugins.PluginManager;
@@ -45,7 +46,9 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
@@ -57,21 +60,37 @@
private TileServices mTileService;
private ArrayList<TileServiceManager> mManagers;
+ @Mock
+ private BroadcastDispatcher mBroadcastDispatcher;
+ @Mock
+ private StatusBarIconController mStatusBarIconController;
+ @Mock
+ private QSFactoryImpl mQSFactory;
+ @Mock
+ private PluginManager mPluginManager;
+ @Mock
+ private TunerService mTunerService;
+ @Mock
+ private AutoTileManager mAutoTileManager;
+ @Mock
+ private DumpController mDumpController;
@Before
public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
mDependency.injectMockDependency(BluetoothController.class);
mManagers = new ArrayList<>();
QSTileHost host = new QSTileHost(mContext,
- mock(StatusBarIconController.class),
- mock(QSFactoryImpl.class),
+ mStatusBarIconController,
+ mQSFactory,
new Handler(),
Looper.myLooper(),
- mock(PluginManager.class),
- mock(TunerService.class),
- () -> mock(AutoTileManager.class),
- mock(DumpController.class));
- mTileService = new TestTileServices(host, Looper.getMainLooper());
+ mPluginManager,
+ mTunerService,
+ () -> mAutoTileManager,
+ mDumpController,
+ mBroadcastDispatcher);
+ mTileService = new TestTileServices(host, Looper.getMainLooper(), mBroadcastDispatcher);
}
@After
@@ -138,12 +157,14 @@
}
private class TestTileServices extends TileServices {
- public TestTileServices(QSTileHost host, Looper looper) {
- super(host, looper);
+ TestTileServices(QSTileHost host, Looper looper,
+ BroadcastDispatcher broadcastDispatcher) {
+ super(host, looper, broadcastDispatcher);
}
@Override
- protected TileServiceManager onCreateTileService(ComponentName component, Tile qsTile) {
+ protected TileServiceManager onCreateTileService(ComponentName component, Tile qsTile,
+ BroadcastDispatcher broadcastDispatcher) {
TileServiceManager manager = mock(TileServiceManager.class);
mManagers.add(manager);
when(manager.isLifecycleStarted()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
new file mode 100644
index 0000000..99850e7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotNotificationSmartActionsTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.screenshot;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.graphics.Bitmap;
+import android.os.Handler;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SystemUIFactory;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+/**
+ * Tests for exception handling and bitmap configuration in adding smart actions to Screenshot
+ * Notification.
+ */
+public class ScreenshotNotificationSmartActionsTest extends SysuiTestCase {
+ private ScreenshotNotificationSmartActionsProvider mSmartActionsProvider;
+ private Handler mHandler;
+
+ @Before
+ public void setup() {
+ mSmartActionsProvider = mock(
+ ScreenshotNotificationSmartActionsProvider.class);
+ mHandler = mock(Handler.class);
+ }
+
+ // Tests any exception thrown in getting smart actions future does not affect regular
+ // screenshot flow.
+ @Test
+ public void testExceptionHandlingInGetSmartActionsFuture()
+ throws Exception {
+ Bitmap bitmap = mock(Bitmap.class);
+ when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
+ ScreenshotNotificationSmartActionsProvider smartActionsProvider = mock(
+ ScreenshotNotificationSmartActionsProvider.class);
+ when(smartActionsProvider.getActions(any(), any(), any(), any(), any(),
+ eq(false))).thenThrow(
+ RuntimeException.class);
+ CompletableFuture<List<Notification.Action>> smartActionsFuture =
+ GlobalScreenshot.getSmartActionsFuture(mContext, bitmap,
+ smartActionsProvider, mHandler, true, false);
+ Assert.assertNotNull(smartActionsFuture);
+ List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
+ Assert.assertEquals(Collections.emptyList(), smartActions);
+ }
+
+ // Tests any exception thrown in waiting for smart actions future to complete does
+ // not affect regular screenshot flow.
+ @Test
+ public void testExceptionHandlingInGetSmartActions()
+ throws Exception {
+ CompletableFuture<List<Notification.Action>> smartActionsFuture = mock(
+ CompletableFuture.class);
+ int timeoutMs = 1000;
+ when(smartActionsFuture.get(timeoutMs, TimeUnit.MILLISECONDS)).thenThrow(
+ RuntimeException.class);
+ List<Notification.Action> actions = GlobalScreenshot.getSmartActions(
+ smartActionsFuture, timeoutMs);
+ Assert.assertEquals(Collections.emptyList(), actions);
+ }
+
+ // Tests for a non-hardware bitmap, ScreenshotNotificationSmartActionsProvider is never invoked
+ // and a completed future is returned.
+ @Test
+ public void testUnsupportedBitmapConfiguration()
+ throws Exception {
+ Bitmap bitmap = mock(Bitmap.class);
+ when(bitmap.getConfig()).thenReturn(Bitmap.Config.RGB_565);
+ CompletableFuture<List<Notification.Action>> smartActionsFuture =
+ GlobalScreenshot.getSmartActionsFuture(mContext, bitmap,
+ mSmartActionsProvider, mHandler, true, true);
+ verify(mSmartActionsProvider, never()).getActions(any(), any(), any(), any(), any(),
+ eq(false));
+ Assert.assertNotNull(smartActionsFuture);
+ List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
+ Assert.assertEquals(Collections.emptyList(), smartActions);
+ }
+
+ // Tests for a hardware bitmap, ScreenshotNotificationSmartActionsProvider is invoked once.
+ @Test
+ public void testScreenshotNotificationSmartActionsProviderInvokedOnce() {
+ Bitmap bitmap = mock(Bitmap.class);
+ when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
+ GlobalScreenshot.getSmartActionsFuture(mContext, bitmap, mSmartActionsProvider,
+ mHandler, true, true);
+ verify(mSmartActionsProvider, times(1))
+ .getActions(any(), any(), any(), any(), any(), eq(true));
+ }
+
+ // Tests for a hardware bitmap, a completed future is returned.
+ @Test
+ public void testSupportedBitmapConfiguration()
+ throws Exception {
+ Bitmap bitmap = mock(Bitmap.class);
+ when(bitmap.getConfig()).thenReturn(Bitmap.Config.HARDWARE);
+ ScreenshotNotificationSmartActionsProvider actionsProvider =
+ SystemUIFactory.getInstance().createScreenshotNotificationSmartActionsProvider();
+ CompletableFuture<List<Notification.Action>> smartActionsFuture =
+ GlobalScreenshot.getSmartActionsFuture(mContext, bitmap,
+ actionsProvider,
+ mHandler, true, true);
+ Assert.assertNotNull(smartActionsFuture);
+ List<Notification.Action> smartActions = smartActionsFuture.get(5, TimeUnit.MILLISECONDS);
+ Assert.assertEquals(smartActions.size(), 0);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/CurrentUserTrackerTest.java b/packages/SystemUI/tests/src/com/android/systemui/settings/CurrentUserTrackerTest.java
index 4162bc1..1b515c6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/CurrentUserTrackerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/CurrentUserTrackerTest.java
@@ -21,9 +21,12 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
/**
* Testing functionality of the current user tracker
@@ -33,10 +36,13 @@
private CurrentUserTracker mTracker;
private CurrentUserTracker.UserReceiver mReceiver;
+ @Mock
+ private BroadcastDispatcher mBroadcastDispatcher;
@Before
public void setUp() {
- mReceiver = new CurrentUserTracker.UserReceiver(getContext());
+ MockitoAnnotations.initMocks(this);
+ mReceiver = new CurrentUserTracker.UserReceiver(mBroadcastDispatcher);
mTracker = new CurrentUserTracker(mReceiver) {
@Override
public void onUserSwitched(int newUserId) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java
index cfa4065a..3c66ac6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NavigationBarControllerTest.java
@@ -62,9 +62,9 @@
@Before
public void setUp() {
- mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
mNavigationBarController = spy(
- new NavigationBarController(mContext, Dependency.get(Dependency.MAIN_HANDLER)));
+ new NavigationBarController(mContext, Dependency.get(Dependency.MAIN_HANDLER),
+ mock(CommandQueue.class)));
initializeNavigationBars();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index 85a0fbd..548f7a8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -47,6 +47,7 @@
import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -74,6 +75,7 @@
@Mock private NotificationData mNotificationData;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@Mock private StatusBarKeyguardViewManager mKeyguardViewManager;
+ @Mock private BroadcastDispatcher mBroadcastDispatcher;
private int mCurrentUserId;
private TestNotificationLockscreenUserManager mLockscreenUserManager;
@@ -194,7 +196,7 @@
private class TestNotificationLockscreenUserManager
extends NotificationLockscreenUserManagerImpl {
public TestNotificationLockscreenUserManager(Context context) {
- super(context);
+ super(context, mBroadcastDispatcher);
}
public BroadcastReceiver getBaseBroadcastReceiverForTest() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
index 2514c93..a754a00d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
@@ -31,6 +31,7 @@
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.google.android.collect.Sets;
@@ -57,6 +58,7 @@
@Mock private NotificationListenerService.RankingMap mRanking;
@Mock private ExpandableNotificationRow mRow;
@Mock private StatusBarStateController mStateController;
+ @Mock private RemoteInputUriController mRemoteInputUriController;
// Dependency mocks:
@Mock private NotificationEntryManager mEntryManager;
@@ -76,7 +78,8 @@
mLockscreenUserManager, mSmartReplyController, mEntryManager,
() -> mock(ShadeController.class),
mStateController,
- Handler.createAsync(Looper.myLooper()));
+ Handler.createAsync(Looper.myLooper()),
+ mRemoteInputUriController);
mEntry = new NotificationEntryBuilder()
.setPkg(TEST_PACKAGE_NAME)
.setOpPkg(TEST_PACKAGE_NAME)
@@ -211,9 +214,11 @@
NotificationEntryManager notificationEntryManager,
Lazy<ShadeController> shadeController,
StatusBarStateController statusBarStateController,
- Handler mainHandler) {
+ Handler mainHandler,
+ RemoteInputUriController remoteInputUriController) {
super(context, lockscreenUserManager, smartReplyController, notificationEntryManager,
- shadeController, statusBarStateController, mainHandler);
+ shadeController, statusBarStateController, mainHandler,
+ remoteInputUriController);
}
public void setUpWithPresenterForTest(Callback callback,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
index 88fb3e1..95ce53c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
@@ -42,6 +42,7 @@
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
import org.junit.Before;
import org.junit.Test;
@@ -72,6 +73,7 @@
@Mock private NotificationEntryManager mNotificationEntryManager;
@Mock private IStatusBarService mIStatusBarService;
@Mock private StatusBarStateController mStatusBarStateController;
+ @Mock private RemoteInputUriController mRemoteInputUriController;
@Before
public void setUp() {
@@ -88,7 +90,8 @@
mock(NotificationLockscreenUserManager.class), mSmartReplyController,
mNotificationEntryManager, () -> mock(ShadeController.class),
mStatusBarStateController,
- Handler.createAsync(Looper.myLooper()));
+ Handler.createAsync(Looper.myLooper()),
+ mRemoteInputUriController);
mRemoteInputManager.setUpWithCallback(mCallback, mDelegate);
mNotification = new Notification.Builder(mContext, "")
.setSmallIcon(R.drawable.ic_person)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt
index a1822c7..f5d6f22 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt
@@ -50,19 +50,14 @@
fun testBindViewModelToViewBoundary() {
val fakePerson1 = fakePersonViewModel("name")
val fakeViewModel = PeopleHubViewModel(sequenceOf(fakePerson1), true)
-
val fakePersonViewAdapter1 = FakeDataListener<PersonViewModel?>()
val fakePersonViewAdapter2 = FakeDataListener<PersonViewModel?>()
-
val mockClickView = mock(View::class.java)
-
`when`(mockViewBoundary.associatedViewForClickAnimation).thenReturn(mockClickView)
`when`(mockViewBoundary.personViewAdapters)
.thenReturn(sequenceOf(fakePersonViewAdapter1, fakePersonViewAdapter2))
-
val mockFactory = mock(PeopleHubViewModelFactory::class.java)
`when`(mockFactory.createWithAssociatedClickView(any())).thenReturn(fakeViewModel)
-
val mockSubscription = mock(Subscription::class.java)
val fakeFactoryDataSource = object : DataSource<PeopleHubViewModelFactory> {
override fun registerListener(
@@ -82,6 +77,7 @@
verify(mockFactory).createWithAssociatedClickView(mockClickView)
}
+ @Test
fun testViewModelDataSourceTransformsModel() {
val fakeClickIntent = PendingIntent.getActivity(context, 0, Intent("action"), 0)
val fakePerson = fakePersonModel("id", "name", fakeClickIntent)
@@ -99,16 +95,17 @@
val mockClickView = mock(View::class.java)
factoryDataSource.registerListener(fakeListener)
+
val viewModel = (fakeListener.lastSeen as Maybe.Just).value
.createWithAssociatedClickView(mockClickView)
assertThat(viewModel.isVisible).isTrue()
-
val people = viewModel.people.toList()
assertThat(people.size).isEqualTo(1)
assertThat(people[0].name).isEqualTo("name")
assertThat(people[0].icon).isSameAs(fakePerson.avatar)
people[0].onClick()
+
verify(mockActivityStarter).startPendingIntentDismissingKeyguard(
same(fakeClickIntent),
any(),
@@ -117,16 +114,20 @@
}
}
+/** Works around Mockito matchers returning `null` and breaking non-nullable Kotlin code. */
private inline fun <reified T : Any> any(): T {
return Mockito.any() ?: createInstance(T::class)
}
+/** Works around Mockito matchers returning `null` and breaking non-nullable Kotlin code. */
private inline fun <reified T : Any> same(value: T): T {
return Mockito.same(value) ?: createInstance(T::class)
}
+/** Creates an instance of the given class. */
private fun <T : Any> createInstance(clazz: KClass<T>): T = castNull()
+/** Tricks the Kotlin compiler into assigning `null` to a non-nullable variable. */
@Suppress("UNCHECKED_CAST")
private fun <T> castNull(): T = null as T
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index 5e6c963..d17c573 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -226,7 +226,7 @@
any(NotificationMenuRowPlugin.MenuItem.class));
reset(listener);
- mGroupRow.setDismissed(true);
+ mGroupRow.dismiss(true);
mGroupRow.doLongClickCallback(0,0);
verify(listener, times(0)).onLongPress(eq(mGroupRow), eq(0), eq(0),
any(NotificationMenuRowPlugin.MenuItem.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index 4a0b371..4451fa4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -38,6 +38,7 @@
import com.android.internal.logging.MetricsLogger;
import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.DumpController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -55,6 +56,8 @@
public class BiometricsUnlockControllerTest extends SysuiTestCase {
@Mock
+ private DumpController mDumpController;
+ @Mock
private NotificationMediaManager mMediaManager;
@Mock
private PowerManager mPowerManager;
@@ -101,7 +104,7 @@
mBiometricUnlockController = new BiometricUnlockController(mContext, mDozeScrimController,
mKeyguardViewMediator, mScrimController, mStatusBar, mKeyguardStateController,
mHandler, mUpdateMonitor, res.getResources(), mKeyguardBypassController,
- mDozeParameters, mMetricsLogger);
+ mDozeParameters, mMetricsLogger, mDumpController);
mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index 0216d2e..0260269 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -33,6 +33,7 @@
import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.HeadsUpStatusBarView;
import com.android.systemui.statusbar.NotificationTestHelper;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
@@ -63,6 +64,7 @@
private KeyguardBypassController mBypassController;
private NotificationWakeUpCoordinator mWakeUpCoordinator;
private KeyguardStateController mKeyguardStateController;
+ private CommandQueue mCommandQueue;
@Before
public void setUp() throws Exception {
@@ -78,6 +80,7 @@
mBypassController = mock(KeyguardBypassController.class);
mWakeUpCoordinator = mock(NotificationWakeUpCoordinator.class);
mKeyguardStateController = mock(KeyguardStateController.class);
+ mCommandQueue = mock(CommandQueue.class);
mHeadsUpAppearanceController = new HeadsUpAppearanceController(
mock(NotificationIconAreaController.class),
mHeadsUpManager,
@@ -85,6 +88,7 @@
mBypassController,
mWakeUpCoordinator,
mKeyguardStateController,
+ mCommandQueue,
mHeadsUpStatusBarView,
mStackScroller,
mPanelView,
@@ -163,6 +167,7 @@
mBypassController,
mWakeUpCoordinator,
mKeyguardStateController,
+ mCommandQueue,
mHeadsUpStatusBarView,
mStackScroller,
mPanelView,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java
index b1580ee..0bcc3af 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarTransitionsControllerTest.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.phone;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -51,10 +50,10 @@
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
mDependency.injectMockDependency(KeyguardStateController.class);
mDependency.injectMockDependency(StatusBarStateController.class);
- mLightBarTransitionsController = new LightBarTransitionsController(mContext, mApplier);
+ mLightBarTransitionsController = new LightBarTransitionsController(mContext, mApplier,
+ new CommandQueue(mContext));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index 237f6ac..2779701 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -95,6 +95,8 @@
private SysUiState mMockSysUiState;
@Mock
private BroadcastDispatcher mBroadcastDispatcher;
+ @Mock
+ private Divider mDivider;
private AccessibilityManagerWrapper mAccessibilityWrapper =
new AccessibilityManagerWrapper(mContext) {
@@ -124,6 +126,7 @@
public void setupFragment() throws Exception {
MockitoAnnotations.initMocks(this);
+ mCommandQueue = new CommandQueue(mContext);
setupSysuiDependency();
createRootView();
mOverviewProxyService =
@@ -150,20 +153,15 @@
}
private void setupSysuiDependency() {
- mCommandQueue = new CommandQueue(mContext);
- mSysuiContext.putComponent(CommandQueue.class, mCommandQueue);
mSysuiContext.putComponent(StatusBar.class, mock(StatusBar.class));
mSysuiContext.putComponent(Recents.class, mock(Recents.class));
- mSysuiContext.putComponent(Divider.class, mock(Divider.class));
Display display = new Display(DisplayManagerGlobal.getInstance(), EXTERNAL_DISPLAY_ID,
new DisplayInfo(), DEFAULT_DISPLAY_ADJUSTMENTS);
mSysuiTestableContextExternal = (SysuiTestableContext) mSysuiContext.createDisplayContext(
display);
- mSysuiTestableContextExternal.putComponent(CommandQueue.class, mCommandQueue);
mSysuiTestableContextExternal.putComponent(StatusBar.class, mock(StatusBar.class));
mSysuiTestableContextExternal.putComponent(Recents.class, mock(Recents.class));
- mSysuiTestableContextExternal.putComponent(Divider.class, mock(Divider.class));
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
WindowManager windowManager = mock(WindowManager.class);
@@ -252,7 +250,9 @@
mock(NavigationModeController.class),
mock(StatusBarStateController.class),
mMockSysUiState,
- mBroadcastDispatcher);
+ mBroadcastDispatcher,
+ mCommandQueue,
+ mDivider);
}
private class HostCallbacksForExternalDisplay extends
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java
index 1e9378a..27a5002 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarTransitionsTest.java
@@ -54,11 +54,10 @@
mDependency.injectMockDependency(StatusBarStateController.class);
mDependency.injectMockDependency(KeyguardStateController.class);
- mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
NavigationBarView navBar = spy(new NavigationBarView(mContext, null));
when(navBar.getCurrentView()).thenReturn(navBar);
when(navBar.findViewById(anyInt())).thenReturn(navBar);
- mTransitions = new NavigationBarTransitions(navBar);
+ mTransitions = new NavigationBarTransitions(navBar, mock(CommandQueue.class));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 4853f20..280cc90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -45,6 +45,7 @@
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationShelf;
@@ -246,7 +247,8 @@
mock(KeyguardStateController.class),
statusBarStateController,
mock(DozeLog.class),
- mDozeParameters);
+ mDozeParameters,
+ new CommandQueue(NotificationPanelViewTest.this.mContext));
mNotificationStackScroller = mNotificationStackScrollLayout;
mKeyguardStatusView = NotificationPanelViewTest.this.mKeyguardStatusView;
mKeyguardStatusBar = NotificationPanelViewTest.this.mKeyguardStatusBar;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
index a27ed1e..7b7e2d3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
@@ -31,6 +31,7 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.StatusBarMobileView;
import com.android.systemui.statusbar.StatusBarWifiView;
@@ -59,14 +60,14 @@
@Test
public void testSetCalledOnAdd_IconManager() {
LinearLayout layout = new LinearLayout(mContext);
- TestIconManager manager = new TestIconManager(layout);
+ TestIconManager manager = new TestIconManager(layout, new CommandQueue(mContext));
testCallOnAdd_forManager(manager);
}
@Test
public void testSetCalledOnAdd_DarkIconManager() {
LinearLayout layout = new LinearLayout(mContext);
- TestDarkIconManager manager = new TestDarkIconManager(layout);
+ TestDarkIconManager manager = new TestDarkIconManager(layout, new CommandQueue(mContext));
testCallOnAdd_forManager(manager);
}
@@ -103,8 +104,8 @@
private static class TestDarkIconManager extends DarkIconManager
implements TestableIconManager {
- public TestDarkIconManager(LinearLayout group) {
- super(group);
+ TestDarkIconManager(LinearLayout group, CommandQueue commandQueue) {
+ super(group, commandQueue);
}
@Override
@@ -138,8 +139,8 @@
}
private static class TestIconManager extends IconManager implements TestableIconManager {
- public TestIconManager(ViewGroup group) {
- super(group);
+ TestIconManager(ViewGroup group, CommandQueue commandQueue) {
+ super(group, commandQueue);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index c0c42ef..de87d31 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -86,7 +86,6 @@
mMetricsLogger = new FakeMetricsLogger();
mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
mCommandQueue = new CommandQueue(mContext);
- mContext.putComponent(CommandQueue.class, mCommandQueue);
mDependency.injectTestDependency(StatusBarStateController.class,
mock(SysuiStatusBarStateController.class));
mDependency.injectTestDependency(ShadeController.class, mShadeController);
@@ -115,7 +114,8 @@
mock(DozeScrimController.class), mock(ScrimController.class),
mock(ActivityLaunchAnimator.class), mock(DynamicPrivacyController.class),
mock(NotificationAlertingManager.class),
- mock(NotificationRowBinderImpl.class), mock(KeyguardStateController.class));
+ mock(NotificationRowBinderImpl.class), mock(KeyguardStateController.class),
+ mCommandQueue);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
index a65f5a5..b1b66b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallbackTest.java
@@ -68,12 +68,11 @@
mDependency.injectTestDependency(ShadeController.class, mShadeController);
mDependency.injectTestDependency(NotificationLockscreenUserManager.class,
mNotificationLockscreenUserManager);
- mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
mRemoteInputCallback = spy(new StatusBarRemoteInputCallback(mContext,
mock(NotificationGroupManager.class), mNotificationLockscreenUserManager,
mKeyguardStateController, mStatusBarStateController, mActivityStarter,
- mShadeController));
+ mShadeController, new CommandQueue(mContext)));
mRemoteInputCallback.mChallengeReceiver = mRemoteInputCallback.new ChallengeReceiver();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 66c01ca..1db926d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -91,6 +91,8 @@
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -106,6 +108,7 @@
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
@@ -130,9 +133,9 @@
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
+import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.util.InjectionInflationController;
import org.junit.Before;
import org.junit.Test;
@@ -143,6 +146,7 @@
import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Optional;
import dagger.Lazy;
@@ -155,7 +159,6 @@
private FakeMetricsLogger mMetricsLogger;
private PowerManager mPowerManager;
private TestableNotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
- private CommandQueue mCommandQueue;
@Mock private FeatureFlags mFeatureFlags;
@Mock private LightBarController mLightBarController;
@@ -181,6 +184,7 @@
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@Mock private NotificationRemoteInputManager mRemoteInputManager;
@Mock private RemoteInputController mRemoteInputController;
+ @Mock private RemoteInputUriController mRemoteInputUriController;
@Mock private StatusBarStateControllerImpl mStatusBarStateController;
@Mock private BatteryController mBatteryController;
@Mock private DeviceProvisionedController mDeviceProvisionedController;
@@ -206,7 +210,6 @@
@Mock private PulseExpansionHandler mPulseExpansionHandler;
@Mock private NotificationWakeUpCoordinator mNotificationWakeUpCoordinator;
@Mock private KeyguardBypassController mKeyguardBypassController;
- @Mock private InjectionInflationController mInjectionInflationController;
@Mock private DynamicPrivacyController mDynamicPrivacyController;
@Mock private NewNotifPipeline mNewNotifPipeline;
@Mock private ZenModeController mZenModeController;
@@ -229,6 +232,11 @@
@Mock private DozeServiceHost mDozeServiceHost;
@Mock private LinearLayout mLockIconContainer;
@Mock private ViewMediatorCallback mKeyguardVieMediatorCallback;
+ @Mock private KeyguardLiftController mKeyguardLiftController;
+ @Mock private CommandQueue mCommandQueue;
+ @Mock private PluginManager mPluginManager;
+ @Mock private Divider mDivider;
+ @Mock private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
@Before
public void setup() throws Exception {
@@ -256,9 +264,7 @@
mExpansionStateLogger);
notificationLogger.setVisibilityReporter(mock(Runnable.class));
- mCommandQueue = mock(CommandQueue.class);
when(mCommandQueue.asBinder()).thenReturn(new Binder());
- mContext.putComponent(CommandQueue.class, mCommandQueue);
mContext.setTheme(R.style.Theme_SystemUI_Light);
@@ -306,7 +312,6 @@
mKeyguardUpdateMonitor,
mStatusBarIconController,
mDozeLog,
- mInjectionInflationController,
mPulseExpansionHandler,
mNotificationWakeUpCoordinator,
mKeyguardBypassController,
@@ -320,7 +325,8 @@
mBroadcastDispatcher,
new RemoteInputQuickSettingsDisabler(
mContext,
- configurationController
+ configurationController,
+ mCommandQueue
),
mNotificationGutsManager,
notificationLogger,
@@ -360,11 +366,17 @@
mNotifLog,
mDozeParameters,
mScrimController,
+ mKeyguardLiftController,
mLockscreenWallpaperLazy,
mBiometricUnlockControllerLazy,
mDozeServiceHost,
mPowerManager,
- mDozeScrimController);
+ mDozeScrimController,
+ mCommandQueue,
+ mPluginManager,
+ mRemoteInputUriController,
+ Optional.of(mDivider),
+ mSuperStatusBarViewFactory);
when(mStatusBarWindowView.findViewById(R.id.lock_icon_container)).thenReturn(
mLockIconContainer);
@@ -382,7 +394,6 @@
mStatusBar.mComponents = mContext.getComponents();
mStatusBar.mStatusBarWindow = mStatusBarWindowView;
mStatusBar.mNotificationPanel = mNotificationPanelView;
- mStatusBar.mCommandQueue = mCommandQueue;
mStatusBar.mDozeScrimController = mDozeScrimController;
mStatusBar.mNotificationIconAreaController = mNotificationIconAreaController;
mStatusBar.mPresenter = mNotificationPresenter;
@@ -391,7 +402,6 @@
mStatusBar.mStackScroller = mStackScroller;
mStatusBar.mStatusBarWindowViewController = mStatusBarWindowViewController;
mStatusBar.startKeyguard();
- mStatusBar.putComponent(StatusBar.class, mStatusBar);
Dependency.get(InitController.class).executePostInitTasks();
entryManager.setUpForTest(mock(NotificationPresenter.class), mStackScroller,
mHeadsUpManager);
@@ -401,7 +411,6 @@
@Test
public void testSetBouncerShowing_noCrash() {
- mStatusBar.mCommandQueue = mock(CommandQueue.class);
mStatusBar.setBouncerShowing(true);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
index a21a658..147edf6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
@@ -25,9 +25,9 @@
import static org.mockito.Mockito.when;
import android.app.IActivityManager;
+import android.content.res.Resources;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
-import android.view.ViewGroup;
import android.view.WindowManager;
import androidx.test.filters.SmallTest;
@@ -35,6 +35,7 @@
import com.android.internal.colorextraction.ColorExtractor;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -52,13 +53,15 @@
@Mock private WindowManager mWindowManager;
@Mock private DozeParameters mDozeParameters;
- @Mock private ViewGroup mStatusBarView;
+ @Mock private StatusBarWindowView mStatusBarView;
@Mock private IActivityManager mActivityManager;
@Mock private SysuiStatusBarStateController mStatusBarStateController;
@Mock private ConfigurationController mConfigurationController;
@Mock private KeyguardBypassController mKeyguardBypassController;
@Mock private SysuiColorExtractor mColorExtractor;
@Mock ColorExtractor.GradientColors mGradientColors;
+ @Mock private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
+ @Mock private Resources mResources;
private StatusBarWindowController mStatusBarWindowController;
@@ -67,11 +70,14 @@
MockitoAnnotations.initMocks(this);
when(mDozeParameters.getAlwaysOn()).thenReturn(true);
when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors);
+ when(mSuperStatusBarViewFactory.getStatusBarWindowView()).thenReturn(mStatusBarView);
mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
mActivityManager, mDozeParameters, mStatusBarStateController,
- mConfigurationController, mKeyguardBypassController, mColorExtractor);
- mStatusBarWindowController.add(mStatusBarView, 100 /* height */);
+ mConfigurationController, mKeyguardBypassController, mColorExtractor,
+ mSuperStatusBarViewFactory, mResources);
+
+ mStatusBarWindowController.attach();
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
index 7c1dfa6..bf81325 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowViewTest.java
@@ -31,9 +31,11 @@
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -71,6 +73,7 @@
@Mock private StatusBar mStatusBar;
@Mock private DozeLog mDozeLog;
@Mock private DozeParameters mDozeParameters;
+ @Mock private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
@Before
public void setUp() {
@@ -81,6 +84,8 @@
when(mStatusBar.isDozing()).thenReturn(false);
mDependency.injectTestDependency(ShadeController.class, mShadeController);
+ when(mSuperStatusBarViewFactory.getStatusBarWindowView()).thenReturn(mView);
+
mController = new StatusBarWindowViewController.Builder(
new InjectionInflationController(
SystemUIFactory.getInstance().getRootComponent()),
@@ -96,9 +101,10 @@
mKeyguardStateController,
mStatusBarStateController,
mDozeLog,
- mDozeParameters)
+ mDozeParameters,
+ new CommandQueue(mContext),
+ mSuperStatusBarViewFactory)
.setShadeController(mShadeController)
- .setStatusBarWindowView(mView)
.build();
mController.setService(mStatusBar);
mController.setDragDownHelper(mDragDownHelper);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
index e626d08..48ed4ba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryControllerTest.java
@@ -27,6 +27,7 @@
import android.testing.TestableLooper;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.power.EnhancedEstimates;
import org.junit.Assert;
@@ -44,13 +45,15 @@
@Mock
private PowerManager mPowerManager;
+ @Mock
+ private BroadcastDispatcher mBroadcastDispatcher;
private BatteryControllerImpl mBatteryController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mBatteryController = new BatteryControllerImpl(getContext(), mock(EnhancedEstimates.class),
- mPowerManager);
+ mPowerManager, mBroadcastDispatcher);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
index 3dcb34a..5f772b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/LocationControllerImplTest.java
@@ -27,6 +27,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
import org.junit.Before;
@@ -44,7 +45,8 @@
@Before
public void setup() {
mLocationController = spy(new LocationControllerImpl(mContext,
- TestableLooper.get(this).getLooper()));
+ TestableLooper.get(this).getLooper(),
+ mock(BroadcastDispatcher.class)));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index c03f07e..4d86613 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -56,6 +56,7 @@
import com.android.settingslib.net.DataUsageController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
@@ -93,6 +94,7 @@
protected WifiManager mMockWm;
protected SubscriptionManager mMockSm;
protected TelephonyManager mMockTm;
+ protected BroadcastDispatcher mMockBd;
protected Config mConfig;
protected CallbackHandler mCallbackHandler;
protected SubscriptionDefaults mMockSubDefaults;
@@ -130,6 +132,7 @@
mMockTm = mock(TelephonyManager.class);
mMockSm = mock(SubscriptionManager.class);
mMockCm = mock(ConnectivityManager.class);
+ mMockBd = mock(BroadcastDispatcher.class);
mMockSubDefaults = mock(SubscriptionDefaults.class);
mNetCapabilities = new NetworkCapabilities();
when(mMockCm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(true);
@@ -157,7 +160,7 @@
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler,
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
- mMockSubDefaults, mMockProvisionController);
+ mMockSubDefaults, mMockProvisionController, mMockBd);
setupNetworkController();
// Trigger blank callbacks to always get the current state (some tests don't trigger
@@ -208,7 +211,7 @@
mConfig, TestableLooper.get(this).getLooper(), mCallbackHandler,
mock(AccessPointControllerImpl.class),
mock(DataUsageController.class), mMockSubDefaults,
- mock(DeviceProvisionedController.class));
+ mock(DeviceProvisionedController.class), mMockBd);
setupNetworkController();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index aa4723a..ab74caa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -108,7 +108,7 @@
mConfig, Looper.getMainLooper(), mCallbackHandler,
mock(AccessPointControllerImpl.class),
mock(DataUsageController.class), mMockSubDefaults,
- mock(DeviceProvisionedController.class));
+ mock(DeviceProvisionedController.class), mMockBd);
setupNetworkController();
setupDefaultSignal();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 0b53c48..57dcbf2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -61,7 +61,7 @@
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
mConfig, Looper.getMainLooper(), mCallbackHandler,
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
- mMockSubDefaults, mock(DeviceProvisionedController.class));
+ mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd);
setupNetworkController();
verifyLastMobileDataIndicators(false, -1, 0);
@@ -123,7 +123,7 @@
mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm, mMockSm,
mConfig, Looper.getMainLooper(), mCallbackHandler,
mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
- mMockSubDefaults, mock(DeviceProvisionedController.class));
+ mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd);
setupNetworkController();
// No Subscriptions.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.java
index fea3a08..b359b9c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.java
@@ -35,12 +35,14 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class RemoteInputQuickSettingsDisablerTest extends SysuiTestCase {
+ @Mock
private CommandQueue mCommandQueue;
private RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
@@ -48,11 +50,8 @@
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mCommandQueue = mock(CommandQueue.class);
- mContext.putComponent(CommandQueue.class, mCommandQueue);
-
mRemoteInputQuickSettingsDisabler = new RemoteInputQuickSettingsDisabler(mContext,
- mock(ConfigurationController.class));
+ mock(ConfigurationController.class), mCommandQueue);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
index 97542a9..0c9130d0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
@@ -45,6 +45,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.statusbar.policy.SecurityController.SecurityControllerCallback;
import org.junit.After;
@@ -99,7 +100,7 @@
// TODO: Migrate this test to TestableLooper and use a handler attached
// to that.
mSecurityController = new SecurityControllerImpl(mContext,
- new Handler(Looper.getMainLooper()), this);
+ new Handler(Looper.getMainLooper()), mock(BroadcastDispatcher.class), this);
}
@After
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
index 47e4492..dcf0ef7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
@@ -33,6 +33,7 @@
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.statusbar.policy.ZenModeController.Callback;
import org.junit.Before;
@@ -51,6 +52,8 @@
NotificationManager mNm;
@Mock
ZenModeConfig mConfig;
+ @Mock
+ BroadcastDispatcher mBroadcastDispatcher;
private ZenModeControllerImpl mController;
@@ -60,7 +63,8 @@
mContext.addMockSystemService(NotificationManager.class, mNm);
when(mNm.getZenModeConfig()).thenReturn(mConfig);
- mController = new ZenModeControllerImpl(mContext, Handler.createAsync(Looper.myLooper()));
+ mController = new ZenModeControllerImpl(mContext, Handler.createAsync(Looper.myLooper()),
+ mBroadcastDispatcher);
}
@Test
diff --git a/packages/Tethering/Android.bp b/packages/Tethering/Android.bp
index ca69c18..61bfb92 100644
--- a/packages/Tethering/Android.bp
+++ b/packages/Tethering/Android.bp
@@ -21,11 +21,13 @@
"src/**/*.java",
":framework-tethering-shared-srcs",
":services-tethering-shared-srcs",
+ ":servicescore-tethering-src",
],
static_libs: [
"androidx.annotation_annotation",
"netd_aidl_interface-java",
"networkstack-aidl-interfaces-java",
+ "android.hardware.tetheroffload.control-V1.0-java",
"tethering-client",
],
manifest: "AndroidManifestBase.xml",
@@ -37,11 +39,39 @@
defaults: ["TetheringAndroidLibraryDefaults"],
}
+cc_library_shared {
+ name: "libtetheroffloadjni",
+ srcs: [
+ "jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp",
+ ],
+ shared_libs: [
+ "libnativehelper",
+ "libcutils",
+ "android.hardware.tetheroffload.config@1.0",
+ ],
+ static_libs: [
+ "liblog",
+ "libbase",
+ "libhidlbase",
+ "libutils",
+ ],
+
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ "-Wthread-safety",
+ ],
+}
+
// Common defaults for compiling the actual APK.
java_defaults {
name: "TetheringAppDefaults",
platform_apis: true,
privileged: true,
+ jni_libs: [
+ "libtetheroffloadjni",
+ ],
resource_dirs: [
"res",
],
@@ -67,13 +97,33 @@
// This group will be removed when tethering migration is done.
filegroup {
- name: "tethering-services-srcs",
+ name: "tethering-servicescore-srcs",
srcs: [
+ "src/com/android/server/connectivity/tethering/EntitlementManager.java",
+ "src/com/android/server/connectivity/tethering/OffloadController.java",
+ "src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java",
"src/com/android/server/connectivity/tethering/TetheringConfiguration.java",
+ "src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java",
+ ],
+}
+
+// This group will be removed when tethering migration is done.
+filegroup {
+ name: "tethering-servicesnet-srcs",
+ srcs: [
"src/android/net/dhcp/DhcpServerCallbacks.java",
"src/android/net/dhcp/DhcpServingParamsParcelExt.java",
"src/android/net/ip/IpServer.java",
"src/android/net/ip/RouterAdvertisementDaemon.java",
"src/android/net/util/InterfaceSet.java",
+ "src/android/net/util/PrefixUtils.java",
+ ],
+}
+
+// This group would be removed when tethering migration is done.
+filegroup {
+ name: "tethering-jni-srcs",
+ srcs: [
+ "jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp",
],
}
diff --git a/packages/Tethering/AndroidManifestBase.xml b/packages/Tethering/AndroidManifestBase.xml
index b9cac19..dc013da 100644
--- a/packages/Tethering/AndroidManifestBase.xml
+++ b/packages/Tethering/AndroidManifestBase.xml
@@ -23,7 +23,6 @@
<application
android:label="Tethering"
android:defaultToDeviceProtectedStorage="true"
- android:directBootAware="true"
- android:usesCleartextTraffic="true">
+ android:directBootAware="true">
</application>
</manifest>
diff --git a/services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp b/packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
similarity index 100%
rename from services/core/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
rename to packages/Tethering/jni/com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp
diff --git a/services/net/java/android/net/util/PrefixUtils.java b/packages/Tethering/src/android/net/util/PrefixUtils.java
similarity index 92%
rename from services/net/java/android/net/util/PrefixUtils.java
rename to packages/Tethering/src/android/net/util/PrefixUtils.java
index f60694a..f203e99 100644
--- a/services/net/java/android/net/util/PrefixUtils.java
+++ b/packages/Tethering/src/android/net/util/PrefixUtils.java
@@ -42,16 +42,19 @@
public static final IpPrefix DEFAULT_WIFI_P2P_PREFIX = pfx("192.168.49.0/24");
+ /** Get non forwardable prefixes. */
public static Set<IpPrefix> getNonForwardablePrefixes() {
final HashSet<IpPrefix> prefixes = new HashSet<>();
addNonForwardablePrefixes(prefixes);
return prefixes;
}
+ /** Add non forwardable prefixes. */
public static void addNonForwardablePrefixes(Set<IpPrefix> prefixes) {
Collections.addAll(prefixes, MIN_NON_FORWARDABLE_PREFIXES);
}
+ /** Get local prefixes from |lp|. */
public static Set<IpPrefix> localPrefixesFrom(LinkProperties lp) {
final HashSet<IpPrefix> localPrefixes = new HashSet<>();
if (lp == null) return localPrefixes;
@@ -66,10 +69,12 @@
return localPrefixes;
}
+ /** Convert LinkAddress |addr| to IpPrefix. */
public static IpPrefix asIpPrefix(LinkAddress addr) {
return new IpPrefix(addr.getAddress(), addr.getPrefixLength());
}
+ /** Convert InetAddress |ip| to IpPrefix. */
public static IpPrefix ipAddressAsPrefix(InetAddress ip) {
final int bitLength = (ip instanceof Inet4Address)
? NetworkConstants.IPV4_ADDR_BITS
diff --git a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
similarity index 99%
rename from services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
rename to packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
index f952bce..6b0f1de 100644
--- a/services/core/java/com/android/server/connectivity/tethering/EntitlementManager.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
@@ -87,7 +87,6 @@
private static final int EVENT_MAYBE_RUN_PROVISIONING = 3;
private static final int EVENT_GET_ENTITLEMENT_VALUE = 4;
-
// The ArraySet contains enabled downstream types, ex:
// {@link ConnectivityManager.TETHERING_WIFI}
// {@link ConnectivityManager.TETHERING_USB}
@@ -112,7 +111,6 @@
public EntitlementManager(Context ctx, StateMachine tetherMasterSM, SharedLog log,
int permissionChangeMessageCode, MockableSystemProperties systemProperties) {
-
mContext = ctx;
mLog = log.forSubComponent(TAG);
mCurrentTethers = new ArraySet<Integer>();
@@ -138,7 +136,7 @@
/**
* Ui entitlement check fails in |downstream|.
*
- * @param downstream tethering type from ConnectivityManager.TETHERING_{@code *}.
+ * @param downstream tethering type from ConnectivityManager.TETHERING_{@code *}.
*/
void onUiEntitlementFailed(int downstream);
}
@@ -662,7 +660,6 @@
private void handleGetLatestTetheringEntitlementValue(int downstream, ResultReceiver receiver,
boolean showEntitlementUi) {
-
final TetheringConfiguration config = mFetcher.fetchTetheringConfiguration();
if (!isTetherProvisioningRequired(config)) {
receiver.send(TETHER_ERROR_NO_ERROR, null);
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
similarity index 97%
rename from services/core/java/com/android/server/connectivity/tethering/OffloadController.java
rename to packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
index a3c2998..16734d8 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadController.java
@@ -36,8 +36,8 @@
import android.net.util.IpUtils;
import android.net.util.SharedLog;
import android.os.Handler;
-import android.os.Looper;
import android.os.INetworkManagementService;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.Settings;
@@ -60,7 +60,6 @@
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
/**
* A class to encapsulate the business logic of programming the tethering
@@ -74,7 +73,7 @@
private static final String ANYIP = "0.0.0.0";
private static final ForwardedStats EMPTY_STATS = new ForwardedStats();
- private static enum UpdateType { IF_NEEDED, FORCE };
+ private enum UpdateType { IF_NEEDED, FORCE };
private final Handler mHandler;
private final OffloadHardwareInterface mHwInterface;
@@ -128,6 +127,7 @@
}
}
+ /** Start hardware offload. */
public boolean start() {
if (started()) return true;
@@ -235,6 +235,7 @@
return isStarted;
}
+ /** Stop hardware offload. */
public void stop() {
// Completely stops tethering offload. After this method is called, it is no longer safe to
// call any HAL method, no callbacks from the hardware will be delivered, and any in-flight
@@ -258,7 +259,9 @@
// getTetherStats() is the only function in OffloadController that can be called from
// a different thread. Do not attempt to update stats by querying the offload HAL
// synchronously from a different thread than our Handler thread. http://b/64771555.
- Runnable updateStats = () -> { updateStatsForCurrentUpstream(); };
+ Runnable updateStats = () -> {
+ updateStatsForCurrentUpstream();
+ };
if (Looper.myLooper() == mHandler.getLooper()) {
updateStats.run();
} else {
@@ -358,6 +361,7 @@
}
}
+ /** Set current tethering upstream LinkProperties. */
public void setUpstreamLinkProperties(LinkProperties lp) {
if (!started() || Objects.equals(mUpstreamLinkProperties, lp)) return;
@@ -376,6 +380,7 @@
pushUpstreamParameters(prevUpstream);
}
+ /** Set local prefixes. */
public void setLocalPrefixes(Set<IpPrefix> localPrefixes) {
mExemptPrefixes = localPrefixes;
@@ -383,6 +388,7 @@
computeAndPushLocalPrefixes(UpdateType.IF_NEEDED);
}
+ /** Update current downstream LinkProperties. */
public void notifyDownstreamLinkProperties(LinkProperties lp) {
final String ifname = lp.getInterfaceName();
final LinkProperties oldLp = mDownstreams.put(ifname, new LinkProperties(lp));
@@ -421,6 +427,7 @@
}
}
+ /** Remove downstream interface from offload hardware. */
public void removeDownstreamInterface(String ifname) {
final LinkProperties lp = mDownstreams.remove(ifname);
if (lp == null) return;
@@ -481,7 +488,7 @@
iface, v4addr, v4gateway, (v6gateways.isEmpty() ? null : v6gateways));
if (!success) {
- return success;
+ return success;
}
// Update stats after we've told the hardware to change routing so we don't miss packets.
@@ -545,6 +552,7 @@
return false;
}
+ /** Dump information. */
public void dump(IndentingPrintWriter pw) {
if (isOffloadDisabled()) {
pw.println("Offload disabled");
@@ -630,7 +638,7 @@
if (ip instanceof Inet4Address) {
return (Inet4Address) ip;
}
- } catch (IllegalArgumentException iae) {}
+ } catch (IllegalArgumentException iae) { }
return null;
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
similarity index 81%
rename from services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
rename to packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
index 207f867..01339a4 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
@@ -23,9 +23,9 @@
import android.hardware.tetheroffload.control.V1_0.NatTimeoutUpdate;
import android.hardware.tetheroffload.control.V1_0.NetworkProtocol;
import android.hardware.tetheroffload.control.V1_0.OffloadCallbackEvent;
+import android.net.util.SharedLog;
import android.os.Handler;
import android.os.RemoteException;
-import android.net.util.SharedLog;
import android.system.OsConstants;
import java.util.ArrayList;
@@ -55,18 +55,34 @@
private TetheringOffloadCallback mTetheringOffloadCallback;
private ControlCallback mControlCallback;
+ /** The callback to notify status of offload management process. */
public static class ControlCallback {
+ /** Offload started. */
public void onStarted() {}
+ /**
+ * Offload stopped because an error has occurred in lower layer.
+ */
public void onStoppedError() {}
+ /**
+ * Offload stopped because the device has moved to a bearer on which hardware offload is
+ * not supported. Subsequent calls to setUpstreamParameters and add/removeDownstream will
+ * likely fail and cannot be presumed to be saved inside of the hardware management process.
+ * Upon receiving #onSupportAvailable(), the caller should reprogram the hardware to begin
+ * offload again.
+ */
public void onStoppedUnsupported() {}
+ /** Indicate that offload is able to proivde support for this time. */
public void onSupportAvailable() {}
+ /** Offload stopped because of usage limit reached. */
public void onStoppedLimitReached() {}
+ /** Indicate to update NAT timeout. */
public void onNatTimeoutUpdate(int proto,
String srcAddr, int srcPort,
String dstAddr, int dstPort) {}
}
+ /** The object which records Tx/Rx forwarded bytes. */
public static class ForwardedStats {
public long rxBytes;
public long txBytes;
@@ -76,11 +92,13 @@
txBytes = 0;
}
+ /** Add Tx/Rx bytes. */
public void add(ForwardedStats other) {
rxBytes += other.rxBytes;
txBytes += other.txBytes;
}
+ /** Returns the string representation of this object. */
public String toString() {
return String.format("rx:%s tx:%s", rxBytes, txBytes);
}
@@ -91,14 +109,17 @@
mLog = log.forSubComponent(TAG);
}
+ /** Get default value indicating whether offload is supported. */
public int getDefaultTetherOffloadDisabled() {
return DEFAULT_TETHER_OFFLOAD_DISABLED;
}
+ /** Configure offload management process. */
public boolean initOffloadConfig() {
return configOffload();
}
+ /** Initialize the tethering offload HAL. */
public boolean initOffloadControl(ControlCallback controlCb) {
mControlCallback = controlCb;
@@ -125,8 +146,8 @@
mOffloadControl.initOffload(
mTetheringOffloadCallback,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -134,9 +155,10 @@
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
+ /** Stop IOffloadControl. */
public void stopOffloadControl() {
if (mOffloadControl != null) {
try {
@@ -154,6 +176,7 @@
mLog.log("stopOffloadControl()");
}
+ /** Get Tx/Rx usage from last query. */
public ForwardedStats getForwardedStats(String upstream) {
final String logmsg = String.format("getForwardedStats(%s)", upstream);
@@ -174,6 +197,7 @@
return stats;
}
+ /** Set local prefixes to offload management process. */
public boolean setLocalPrefixes(ArrayList<String> localPrefixes) {
final String logmsg = String.format("setLocalPrefixes([%s])",
String.join(",", localPrefixes));
@@ -182,8 +206,8 @@
try {
mOffloadControl.setLocalPrefixes(localPrefixes,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -191,9 +215,10 @@
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
+ /** Set data limit value to offload management process. */
public boolean setDataLimit(String iface, long limit) {
final String logmsg = String.format("setDataLimit(%s, %d)", iface, limit);
@@ -203,8 +228,8 @@
mOffloadControl.setDataLimit(
iface, limit,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -212,9 +237,10 @@
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
+ /** Set upstream parameters to offload management process. */
public boolean setUpstreamParameters(
String iface, String v4addr, String v4gateway, ArrayList<String> v6gws) {
iface = (iface != null) ? iface : NO_INTERFACE_NAME;
@@ -230,8 +256,8 @@
mOffloadControl.setUpstreamParameters(
iface, v4addr, v4gateway, v6gws,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -239,9 +265,10 @@
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
+ /** Add downstream prefix to offload management process. */
public boolean addDownstreamPrefix(String ifname, String prefix) {
final String logmsg = String.format("addDownstreamPrefix(%s, %s)", ifname, prefix);
@@ -249,8 +276,8 @@
try {
mOffloadControl.addDownstream(ifname, prefix,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -258,9 +285,10 @@
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
+ /** Remove downstream prefix from offload management process. */
public boolean removeDownstreamPrefix(String ifname, String prefix) {
final String logmsg = String.format("removeDownstreamPrefix(%s, %s)", ifname, prefix);
@@ -268,8 +296,8 @@
try {
mOffloadControl.removeDownstream(ifname, prefix,
(boolean success, String errMsg) -> {
- results.success = success;
- results.errMsg = errMsg;
+ results.mSuccess = success;
+ results.mErrMsg = errMsg;
});
} catch (RemoteException e) {
record(logmsg, e);
@@ -277,7 +305,7 @@
}
record(logmsg, results);
- return results.success;
+ return results.mSuccess;
}
private void record(String msg, Throwable t) {
@@ -286,7 +314,7 @@
private void record(String msg, CbResults results) {
final String logmsg = msg + YIELDS + results;
- if (!results.success) {
+ if (!results.mSuccess) {
mLog.e(logmsg);
} else {
mLog.log(logmsg);
@@ -298,7 +326,7 @@
public final ControlCallback controlCb;
public final SharedLog log;
- public TetheringOffloadCallback(Handler h, ControlCallback cb, SharedLog sharedLog) {
+ TetheringOffloadCallback(Handler h, ControlCallback cb, SharedLog sharedLog) {
handler = h;
controlCb = cb;
log = sharedLog;
@@ -332,7 +360,7 @@
@Override
public void updateTimeout(NatTimeoutUpdate params) {
handler.post(() -> {
- controlCb.onNatTimeoutUpdate(
+ controlCb.onNatTimeoutUpdate(
networkProtocolToOsConstant(params.proto),
params.src.addr, uint16(params.src.port),
params.dst.addr, uint16(params.dst.port));
@@ -352,15 +380,15 @@
}
private static class CbResults {
- boolean success;
- String errMsg;
+ boolean mSuccess;
+ String mErrMsg;
@Override
public String toString() {
- if (success) {
+ if (mSuccess) {
return "ok";
} else {
- return "fail: " + errMsg;
+ return "fail: " + mErrMsg;
}
}
}
diff --git a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
similarity index 93%
rename from services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
rename to packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
index 3a9e21f..9769596 100644
--- a/services/core/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitor.java
@@ -146,6 +146,7 @@
}
}
+ /** Listen all networks. */
public void startObserveAllNetworks() {
stop();
@@ -155,6 +156,13 @@
cm().registerNetworkCallback(listenAllRequest, mListenAllCallback, mHandler);
}
+ /**
+ * Stop tracking candidate tethering upstreams and release mobile network request.
+ * Note: this function is used when tethering is stopped because tethering do not need to
+ * choose upstream anymore. But it would not stop default network tracking because
+ * EntitlementManager may need to know default network to decide whether to request entitlement
+ * check even tethering is not active yet.
+ */
public void stop() {
releaseMobileNetworkRequest();
@@ -165,6 +173,7 @@
mNetworkMap.clear();
}
+ /** Setup or teardown DUN connection according to |dunRequired|. */
public void updateMobileRequiresDun(boolean dunRequired) {
final boolean valueChanged = (mDunRequired != dunRequired);
mDunRequired = dunRequired;
@@ -174,10 +183,12 @@
}
}
+ /** Whether mobile network is requested. */
public boolean mobileNetworkRequested() {
return (mMobileNetworkCallback != null);
}
+ /** Request mobile network if mobile upstream is permitted. */
public void registerMobileNetworkRequest() {
if (!isCellularUpstreamPermitted()) {
mLog.i("registerMobileNetworkRequest() is not permitted");
@@ -209,6 +220,7 @@
cm().requestNetwork(mobileUpstreamRequest, mMobileNetworkCallback, 0, legacyType, mHandler);
}
+ /** Release mobile network request. */
public void releaseMobileNetworkRequest() {
if (mMobileNetworkCallback == null) return;
@@ -221,6 +233,9 @@
// becomes available and useful we (a) file a request to keep it up as
// necessary and (b) change all upstream tracking state accordingly (by
// passing LinkProperties up to Tethering).
+ /**
+ * Select the first available network from |perferredTypes|.
+ */
public NetworkState selectPreferredUpstreamType(Iterable<Integer> preferredTypes) {
final TypeStatePair typeStatePair = findFirstAvailableUpstreamByType(
mNetworkMap.values(), preferredTypes, isCellularUpstreamPermitted());
@@ -254,7 +269,11 @@
return typeStatePair.ns;
}
- // Returns null if no current upstream available.
+ /**
+ * Get current preferred upstream network. If default network is cellular and DUN is required,
+ * preferred upstream would be DUN otherwise preferred upstream is the same as default network.
+ * Returns null if no current upstream is available.
+ */
public NetworkState getCurrentPreferredUpstream() {
final NetworkState dfltState = (mDefaultInternetNetwork != null)
? mNetworkMap.get(mDefaultInternetNetwork)
@@ -270,10 +289,12 @@
return findFirstDunNetwork(mNetworkMap.values());
}
+ /** Tell UpstreamNetworkMonitor which network is the current upstream of tethering. */
public void setCurrentUpstream(Network upstream) {
mTetheringUpstreamNetwork = upstream;
}
+ /** Return local prefixes. */
public Set<IpPrefix> getLocalPrefixes() {
return (Set<IpPrefix>) mLocalPrefixes.clone();
}
@@ -501,8 +522,8 @@
try {
nc = ConnectivityManager.networkCapabilitiesForType(type);
} catch (IllegalArgumentException iae) {
- Log.e(TAG, "No NetworkCapabilities mapping for legacy type: " +
- ConnectivityManager.getNetworkTypeName(type));
+ Log.e(TAG, "No NetworkCapabilities mapping for legacy type: "
+ + ConnectivityManager.getNetworkTypeName(type));
continue;
}
if (!isCellularUpstreamPermitted && isCellular(nc)) {
@@ -547,18 +568,18 @@
}
private static boolean isCellular(NetworkCapabilities nc) {
- return (nc != null) && nc.hasTransport(TRANSPORT_CELLULAR) &&
- nc.hasCapability(NET_CAPABILITY_NOT_VPN);
+ return (nc != null) && nc.hasTransport(TRANSPORT_CELLULAR)
+ && nc.hasCapability(NET_CAPABILITY_NOT_VPN);
}
private static boolean hasCapability(NetworkState ns, int netCap) {
- return (ns != null) && (ns.networkCapabilities != null) &&
- ns.networkCapabilities.hasCapability(netCap);
+ return (ns != null) && (ns.networkCapabilities != null)
+ && ns.networkCapabilities.hasCapability(netCap);
}
private static boolean isNetworkUsableAndNotCellular(NetworkState ns) {
- return (ns != null) && (ns.networkCapabilities != null) && (ns.linkProperties != null) &&
- !isCellular(ns.networkCapabilities);
+ return (ns != null) && (ns.networkCapabilities != null) && (ns.linkProperties != null)
+ && !isCellular(ns.networkCapabilities);
}
private static NetworkState findFirstDunNetwork(Iterable<NetworkState> netStates) {
diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp
index da62107..363be18 100644
--- a/packages/Tethering/tests/unit/Android.bp
+++ b/packages/Tethering/tests/unit/Android.bp
@@ -17,11 +17,15 @@
android_test {
name: "TetheringTests",
certificate: "platform",
- srcs: ["src/**/*.java"],
+ srcs: [
+ ":servicescore-tethering-src",
+ "src/**/*.java",
+ ],
test_suites: ["device-tests"],
static_libs: [
"androidx.test.rules",
"frameworks-base-testutils",
+ "net-tests-utils",
"mockito-target-extended-minus-junit4",
"TetheringApiCurrentLib",
"testables",
@@ -42,7 +46,10 @@
filegroup {
name: "tethering-tests-src",
srcs: [
+ "src/com/android/server/connectivity/tethering/EntitlementManagerTest.java",
+ "src/com/android/server/connectivity/tethering/OffloadControllerTest.java",
"src/com/android/server/connectivity/tethering/TetheringConfigurationTest.java",
+ "src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java",
"src/android/net/dhcp/DhcpServingParamsParcelExtTest.java",
"src/android/net/ip/IpServerTest.java",
"src/android/net/util/InterfaceSetTest.java",
diff --git a/tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
similarity index 100%
rename from tests/net/java/com/android/server/connectivity/tethering/EntitlementManagerTest.java
rename to packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
diff --git a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
similarity index 98%
rename from tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
rename to packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
index 9931aec..8574f54 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/OffloadControllerTest.java
@@ -26,10 +26,10 @@
import static com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats;
import static com.android.testutils.MiscAssertsKt.assertContainsAll;
+import static com.android.testutils.MiscAssertsKt.assertThrows;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyObject;
@@ -148,10 +148,8 @@
public void testNoSettingsValueDefaultDisabledDoesNotStart() throws Exception {
setupFunctioningHardwareInterface();
when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(1);
- try {
- Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED);
- fail();
- } catch (SettingNotFoundException expected) {}
+ assertThrows(SettingNotFoundException.class, () ->
+ Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
final OffloadController offload = makeOffloadController();
offload.start();
@@ -168,10 +166,8 @@
public void testNoSettingsValueDefaultEnabledDoesStart() throws Exception {
setupFunctioningHardwareInterface();
when(mHardware.getDefaultTetherOffloadDisabled()).thenReturn(0);
- try {
- Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED);
- fail();
- } catch (SettingNotFoundException expected) {}
+ assertThrows(SettingNotFoundException.class, () ->
+ Settings.Global.getInt(mContentResolver, TETHER_OFFLOAD_DISABLED));
final OffloadController offload = makeOffloadController();
offload.start();
diff --git a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
similarity index 94%
rename from tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
rename to packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
index 0d276cb..c028d6d 100644
--- a/tests/net/java/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/UpstreamNetworkMonitorTest.java
@@ -87,7 +87,7 @@
// Actual contents of the request don't matter for this test. The lack of
// any specific TRANSPORT_* is sufficient to identify this request.
- private static final NetworkRequest mDefaultRequest = new NetworkRequest.Builder().build();
+ private static final NetworkRequest sDefaultRequest = new NetworkRequest.Builder().build();
@Mock private Context mContext;
@Mock private EntitlementManager mEntitleMgr;
@@ -140,7 +140,7 @@
@Test
public void testDefaultNetworkIsTracked() throws Exception {
assertTrue(mCM.hasNoCallbacks());
- mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr);
+ mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
mUNM.startObserveAllNetworks();
assertEquals(1, mCM.trackingDefault.size());
@@ -153,7 +153,7 @@
public void testListensForAllNetworks() throws Exception {
assertTrue(mCM.listening.isEmpty());
- mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr);
+ mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
mUNM.startObserveAllNetworks();
assertFalse(mCM.listening.isEmpty());
assertTrue(mCM.isListeningForAll());
@@ -164,9 +164,9 @@
@Test
public void testCallbacksRegistered() {
- mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr);
+ mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
verify(mCM, times(1)).requestNetwork(
- eq(mDefaultRequest), any(NetworkCallback.class), any(Handler.class));
+ eq(sDefaultRequest), any(NetworkCallback.class), any(Handler.class));
mUNM.startObserveAllNetworks();
verify(mCM, times(1)).registerNetworkCallback(
any(NetworkRequest.class), any(NetworkCallback.class), any(Handler.class));
@@ -191,7 +191,7 @@
mUNM.registerMobileNetworkRequest();
assertTrue(mUNM.mobileNetworkRequested());
assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI);
- assertFalse(mCM.isDunRequested());
+ assertFalse(isDunRequested());
mUNM.stop();
assertFalse(mUNM.mobileNetworkRequested());
@@ -217,7 +217,7 @@
assertTrue(mUNM.mobileNetworkRequested());
assertUpstreamTypeRequested(TYPE_MOBILE_DUN);
- assertTrue(mCM.isDunRequested());
+ assertTrue(isDunRequested());
// Try a few things that must not result in any state change.
mUNM.registerMobileNetworkRequest();
@@ -226,7 +226,7 @@
assertTrue(mUNM.mobileNetworkRequested());
assertUpstreamTypeRequested(TYPE_MOBILE_DUN);
- assertTrue(mCM.isDunRequested());
+ assertTrue(isDunRequested());
mUNM.stop();
verify(mCM, times(2)).unregisterNetworkCallback(any(NetworkCallback.class));
@@ -250,7 +250,7 @@
mUNM.registerMobileNetworkRequest();
assertTrue(mUNM.mobileNetworkRequested());
assertUpstreamTypeRequested(TYPE_MOBILE_DUN);
- assertTrue(mCM.isDunRequested());
+ assertTrue(isDunRequested());
mUNM.stop();
assertFalse(mUNM.mobileNetworkRequested());
@@ -266,17 +266,17 @@
mUNM.registerMobileNetworkRequest();
assertTrue(mUNM.mobileNetworkRequested());
assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI);
- assertFalse(mCM.isDunRequested());
+ assertFalse(isDunRequested());
mUNM.updateMobileRequiresDun(true);
assertTrue(mUNM.mobileNetworkRequested());
assertUpstreamTypeRequested(TYPE_MOBILE_DUN);
- assertTrue(mCM.isDunRequested());
+ assertTrue(isDunRequested());
// Test going from DUN to no-DUN correctly re-registers callbacks.
mUNM.updateMobileRequiresDun(false);
assertTrue(mUNM.mobileNetworkRequested());
assertUpstreamTypeRequested(TYPE_MOBILE_HIPRI);
- assertFalse(mCM.isDunRequested());
+ assertFalse(isDunRequested());
mUNM.stop();
assertFalse(mUNM.mobileNetworkRequested());
@@ -287,7 +287,7 @@
final Collection<Integer> preferredTypes = new ArrayList<>();
preferredTypes.add(TYPE_WIFI);
- mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr);
+ mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
mUNM.startObserveAllNetworks();
// There are no networks, so there is nothing to select.
assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
@@ -369,7 +369,7 @@
@Test
public void testGetCurrentPreferredUpstream() throws Exception {
- mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr);
+ mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
mUNM.startObserveAllNetworks();
mUNM.updateMobileRequiresDun(false);
@@ -418,7 +418,7 @@
@Test
public void testLocalPrefixes() throws Exception {
- mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr);
+ mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
mUNM.startObserveAllNetworks();
// [0] Test minimum set of local prefixes.
@@ -431,13 +431,13 @@
final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI);
final LinkProperties wifiLp = wifiAgent.linkProperties;
wifiLp.setInterfaceName("wlan0");
- final String[] WIFI_ADDRS = {
+ final String[] wifi_addrs = {
"fe80::827a:bfff:fe6f:374d", "100.112.103.18",
"2001:db8:4:fd00:827a:bfff:fe6f:374d",
"2001:db8:4:fd00:6dea:325a:fdae:4ef4",
"fd6a:a640:60bf:e985::123", // ULA address for good measure.
};
- for (String addrStr : WIFI_ADDRS) {
+ for (String addrStr : wifi_addrs) {
final String cidr = addrStr.contains(":") ? "/64" : "/20";
wifiLp.addLinkAddress(new LinkAddress(addrStr + cidr));
}
@@ -458,10 +458,10 @@
final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, TRANSPORT_CELLULAR);
final LinkProperties cellLp = cellAgent.linkProperties;
cellLp.setInterfaceName("rmnet_data0");
- final String[] CELL_ADDRS = {
+ final String[] cell_addrs = {
"10.102.211.48", "2001:db8:0:1:b50e:70d9:10c9:433d",
};
- for (String addrStr : CELL_ADDRS) {
+ for (String addrStr : cell_addrs) {
final String cidr = addrStr.contains(":") ? "/64" : "/27";
cellLp.addLinkAddress(new LinkAddress(addrStr + cidr));
}
@@ -481,10 +481,10 @@
dunAgent.networkCapabilities.removeCapability(NET_CAPABILITY_INTERNET);
final LinkProperties dunLp = dunAgent.linkProperties;
dunLp.setInterfaceName("rmnet_data1");
- final String[] DUN_ADDRS = {
+ final String[] dun_addrs = {
"192.0.2.48", "2001:db8:1:2:b50e:70d9:10c9:433d",
};
- for (String addrStr : DUN_ADDRS) {
+ for (String addrStr : dun_addrs) {
final String cidr = addrStr.contains(":") ? "/64" : "/27";
dunLp.addLinkAddress(new LinkAddress(addrStr + cidr));
}
@@ -525,7 +525,7 @@
// Mobile has higher pirority than wifi.
preferredTypes.add(TYPE_MOBILE_HIPRI);
preferredTypes.add(TYPE_WIFI);
- mUNM.startTrackDefaultNetwork(mDefaultRequest, mEntitleMgr);
+ mUNM.startTrackDefaultNetwork(sDefaultRequest, mEntitleMgr);
mUNM.startObserveAllNetworks();
// Setup wifi and make wifi as default network.
final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, TRANSPORT_WIFI);
@@ -556,6 +556,15 @@
mCM.legacyTypeMap.values().iterator().next());
}
+ private boolean isDunRequested() {
+ for (NetworkRequest req : mCM.requested.values()) {
+ if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public static class TestConnectivityManager extends ConnectivityManager {
public Map<NetworkCallback, Handler> allCallbacks = new HashMap<>();
public Set<NetworkCallback> trackingDefault = new HashSet<>();
@@ -598,17 +607,10 @@
return false;
}
- boolean isDunRequested() {
- for (NetworkRequest req : requested.values()) {
- if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) {
- return true;
- }
- }
- return false;
+ int getNetworkId() {
+ return ++mNetworkId;
}
- int getNetworkId() { return ++mNetworkId; }
-
void makeDefaultNetwork(TestNetworkAgent agent) {
if (Objects.equals(defaultNetwork, agent)) return;
@@ -630,7 +632,7 @@
public void requestNetwork(NetworkRequest req, NetworkCallback cb, Handler h) {
assertFalse(allCallbacks.containsKey(cb));
allCallbacks.put(cb, h);
- if (mDefaultRequest.equals(req)) {
+ if (sDefaultRequest.equals(req)) {
assertFalse(trackingDefault.contains(cb));
trackingDefault.add(cb);
} else {
@@ -749,9 +751,13 @@
private final State mLoggingState = new LoggingState();
class LoggingState extends State {
- @Override public void enter() { messages.clear(); }
+ @Override public void enter() {
+ messages.clear();
+ }
- @Override public void exit() { messages.clear(); }
+ @Override public void exit() {
+ messages.clear();
+ }
@Override public boolean processMessage(Message msg) {
messages.add(msg);
diff --git a/services/Android.bp b/services/Android.bp
index 60dd895..6953e86 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -47,11 +47,6 @@
"compat-changeid-annotation-processor",
],
- required: [
- // Required by services.backup
- "BackupEncryption",
- ],
-
// Uncomment to enable output of certain warnings (deprecated, unchecked)
//javacflags: ["-Xlint"],
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 68e11df32..6f43529 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -67,8 +67,6 @@
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.provider.Settings;
-import android.provider.SettingsStringUtil;
-import android.provider.SettingsStringUtil.ComponentNameSet;
import android.provider.SettingsStringUtil.SettingStringHelper;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
@@ -2219,12 +2217,12 @@
* Enables accessibility service specified by {@param componentName} for the {@param userId}.
*/
private void enableAccessibilityServiceLocked(ComponentName componentName, int userId) {
- final SettingStringHelper setting =
- new SettingStringHelper(
- mContext.getContentResolver(),
- Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
- userId);
- setting.write(ComponentNameSet.add(setting.read(), componentName));
+ mTempComponentNameSet.clear();
+ readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+ userId, mTempComponentNameSet);
+ mTempComponentNameSet.add(componentName);
+ persistComponentNamesToSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+ mTempComponentNameSet, userId);
AccessibilityUserState userState = getUserStateLocked(userId);
if (userState.mEnabledServices.add(componentName)) {
@@ -2236,12 +2234,12 @@
* Disables accessibility service specified by {@param componentName} for the {@param userId}.
*/
private void disableAccessibilityServiceLocked(ComponentName componentName, int userId) {
- final SettingsStringUtil.SettingStringHelper setting =
- new SettingStringHelper(
- mContext.getContentResolver(),
- Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
- userId);
- setting.write(ComponentNameSet.remove(setting.read(), componentName));
+ mTempComponentNameSet.clear();
+ readComponentNamesFromSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+ userId, mTempComponentNameSet);
+ mTempComponentNameSet.remove(componentName);
+ persistComponentNamesToSettingLocked(Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+ mTempComponentNameSet, userId);
AccessibilityUserState userState = getUserStateLocked(userId);
if (userState.mEnabledServices.remove(componentName)) {
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 1fc4751..3cbfcf1 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -40,6 +40,10 @@
import android.service.autofill.SaveInfo;
import android.service.autofill.ValueFinder;
import android.text.Html;
+import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
+import android.text.style.ClickableSpan;
import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
@@ -60,11 +64,14 @@
import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.util.ArrayUtils;
import com.android.server.UiThread;
import com.android.server.autofill.Helper;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
/**
* Autofill Save Prompt
@@ -158,6 +165,7 @@
private final ComponentName mComponentName;
private final boolean mCompatMode;
private final int mThemeId;
+ private final int mType;
private boolean mDestroyed;
@@ -179,8 +187,17 @@
context = new ContextThemeWrapper(context, mThemeId) {
@Override
public void startActivity(Intent intent) {
+ if (intent.resolveActivity(getPackageManager()) == null) {
+ return;
+ }
+ intent.putExtra(AutofillManager.EXTRA_RESTORE_CROSS_ACTIVITY, true);
+
PendingIntent p = PendingIntent.getActivity(this, 0, intent, 0);
- mListener.startIntentSender(p.getIntentSender(), intent);
+ if (sDebug) {
+ Slog.d(TAG, "startActivity add save UI restored with intent=" + intent);
+ }
+ // Apply restore mechanism
+ startIntentSenderWithRestore(p, intent);
}
};
final LayoutInflater inflater = LayoutInflater.from(context);
@@ -189,12 +206,12 @@
final TextView titleView = view.findViewById(R.id.autofill_save_title);
final ArraySet<String> types = new ArraySet<>(3);
- final int type = info.getType();
+ mType = info.getType();
- if ((type & SaveInfo.SAVE_DATA_TYPE_PASSWORD) != 0) {
+ if ((mType & SaveInfo.SAVE_DATA_TYPE_PASSWORD) != 0) {
types.add(context.getString(R.string.autofill_save_type_password));
}
- if ((type & SaveInfo.SAVE_DATA_TYPE_ADDRESS) != 0) {
+ if ((mType & SaveInfo.SAVE_DATA_TYPE_ADDRESS) != 0) {
types.add(context.getString(R.string.autofill_save_type_address));
}
@@ -202,20 +219,20 @@
final int cardTypeMask = SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD
| SaveInfo.SAVE_DATA_TYPE_DEBIT_CARD
| SaveInfo.SAVE_DATA_TYPE_PAYMENT_CARD;
- final int count = Integer.bitCount(type & cardTypeMask);
- if (count > 1 || (type & SaveInfo.SAVE_DATA_TYPE_GENERIC_CARD) != 0) {
+ final int count = Integer.bitCount(mType & cardTypeMask);
+ if (count > 1 || (mType & SaveInfo.SAVE_DATA_TYPE_GENERIC_CARD) != 0) {
types.add(context.getString(R.string.autofill_save_type_generic_card));
- } else if ((type & SaveInfo.SAVE_DATA_TYPE_PAYMENT_CARD) != 0) {
+ } else if ((mType & SaveInfo.SAVE_DATA_TYPE_PAYMENT_CARD) != 0) {
types.add(context.getString(R.string.autofill_save_type_payment_card));
- } else if ((type & SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD) != 0) {
+ } else if ((mType & SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD) != 0) {
types.add(context.getString(R.string.autofill_save_type_credit_card));
- } else if ((type & SaveInfo.SAVE_DATA_TYPE_DEBIT_CARD) != 0) {
+ } else if ((mType & SaveInfo.SAVE_DATA_TYPE_DEBIT_CARD) != 0) {
types.add(context.getString(R.string.autofill_save_type_debit_card));
}
- if ((type & SaveInfo.SAVE_DATA_TYPE_USERNAME) != 0) {
+ if ((mType & SaveInfo.SAVE_DATA_TYPE_USERNAME) != 0) {
types.add(context.getString(R.string.autofill_save_type_username));
}
- if ((type & SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS) != 0) {
+ if ((mType & SaveInfo.SAVE_DATA_TYPE_EMAIL_ADDRESS) != 0) {
types.add(context.getString(R.string.autofill_save_type_email_address));
}
@@ -257,11 +274,12 @@
} else {
mSubTitle = info.getDescription();
if (mSubTitle != null) {
- writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_SUBTITLE, type);
+ writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_SUBTITLE);
final ViewGroup subtitleContainer =
view.findViewById(R.id.autofill_save_custom_subtitle);
final TextView subtitleView = new TextView(context);
subtitleView.setText(mSubTitle);
+ applyMovementMethodIfNeed(subtitleView);
subtitleContainer.addView(subtitleView,
new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
@@ -318,8 +336,7 @@
if (customDescription == null) {
return false;
}
- final int type = info.getType();
- writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_DESCRIPTION, type);
+ writeLog(MetricsEvent.AUTOFILL_SAVE_CUSTOM_DESCRIPTION);
final RemoteViews template = customDescription.getPresentation();
if (template == null) {
@@ -342,26 +359,15 @@
final RemoteViews.OnClickHandler handler = (view, pendingIntent, response) -> {
Intent intent = response.getLaunchOptions(view).first;
- final LogMaker log =
- newLogMaker(MetricsEvent.AUTOFILL_SAVE_LINK_TAPPED, type);
- // We need to hide the Save UI before launching the pending intent, and
- // restore back it once the activity is finished, and that's achieved by
- // adding a custom extra in the activity intent.
final boolean isValid = isValidLink(pendingIntent, intent);
if (!isValid) {
+ final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_SAVE_LINK_TAPPED, mType);
log.setType(MetricsEvent.TYPE_UNKNOWN);
mMetricsLogger.write(log);
return false;
}
- if (sVerbose) Slog.v(TAG, "Intercepting custom description intent");
- final IBinder token = mPendingUi.getToken();
- intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
- mListener.startIntentSender(pendingIntent.getIntentSender(), intent);
- mPendingUi.setState(PendingUi.STATE_PENDING);
- if (sDebug) Slog.d(TAG, "hiding UI until restored with token " + token);
- hide();
- log.setType(MetricsEvent.TYPE_OPEN);
- mMetricsLogger.write(log);
+
+ startIntentSenderWithRestore(pendingIntent, intent);
return true;
};
@@ -442,6 +448,8 @@
}
}
+ applyTextViewStyle(customSubtitleView);
+
// Finally, add the custom description to the save UI.
final ViewGroup subtitleContainer =
saveUiView.findViewById(R.id.autofill_save_custom_subtitle);
@@ -457,6 +465,60 @@
return false;
}
+ private void startIntentSenderWithRestore(@NonNull PendingIntent pendingIntent,
+ @NonNull Intent intent) {
+ if (sVerbose) Slog.v(TAG, "Intercepting custom description intent");
+
+ // We need to hide the Save UI before launching the pending intent, and
+ // restore back it once the activity is finished, and that's achieved by
+ // adding a custom extra in the activity intent.
+ final IBinder token = mPendingUi.getToken();
+ intent.putExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN, token);
+
+ mListener.startIntentSender(pendingIntent.getIntentSender(), intent);
+ mPendingUi.setState(PendingUi.STATE_PENDING);
+
+ if (sDebug) Slog.d(TAG, "hiding UI until restored with token " + token);
+ hide();
+
+ final LogMaker log = newLogMaker(MetricsEvent.AUTOFILL_SAVE_LINK_TAPPED, mType);
+ log.setType(MetricsEvent.TYPE_OPEN);
+ mMetricsLogger.write(log);
+ }
+
+ private void applyTextViewStyle(@NonNull View rootView) {
+ final List<TextView> textViews = new ArrayList<>();
+ final Predicate<View> predicate = (view) -> {
+ if (view instanceof TextView) {
+ // Collects TextViews
+ textViews.add((TextView) view);
+ }
+ return false;
+ };
+
+ // Traverses all TextViews, enables movement method if the TextView contains URLSpan
+ rootView.findViewByPredicate(predicate);
+ final int size = textViews.size();
+ for (int i = 0; i < size; i++) {
+ applyMovementMethodIfNeed(textViews.get(i));
+ }
+ }
+
+ private void applyMovementMethodIfNeed(@NonNull TextView textView) {
+ final CharSequence message = textView.getText();
+ if (TextUtils.isEmpty(message)) {
+ return;
+ }
+
+ final SpannableStringBuilder ssb = new SpannableStringBuilder(message);
+ final ClickableSpan[] spans = ssb.getSpans(0, ssb.length(), ClickableSpan.class);
+ if (ArrayUtils.isEmpty(spans)) {
+ return;
+ }
+
+ textView.setMovementMethod(LinkMovementMethod.getInstance());
+ }
+
private void setServiceIcon(Context context, View view, Drawable serviceIcon) {
final ImageView iconView = view.findViewById(R.id.autofill_save_icon);
final Resources res = context.getResources();
@@ -506,8 +568,8 @@
mPendingUi.sessionId, mCompatMode);
}
- private void writeLog(int category, int saveType) {
- mMetricsLogger.write(newLogMaker(category, saveType));
+ private void writeLog(int category) {
+ mMetricsLogger.write(newLogMaker(category, mType));
}
/**
diff --git a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
index ecea251c..9cdb58d 100644
--- a/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
+++ b/services/contentsuggestions/java/com/android/server/contentsuggestions/ContentSuggestionsManagerService.java
@@ -16,7 +16,6 @@
package com.android.server.contentsuggestions;
-import static android.Manifest.permission.BIND_CONTENT_SUGGESTIONS_SERVICE;
import static android.Manifest.permission.MANAGE_CONTENT_SUGGESTIONS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -96,7 +95,7 @@
private void enforceCaller(int userId, String func) {
Context ctx = getContext();
- if (ctx.checkCallingPermission(BIND_CONTENT_SUGGESTIONS_SERVICE) == PERMISSION_GRANTED
+ if (ctx.checkCallingPermission(MANAGE_CONTENT_SUGGESTIONS) == PERMISSION_GRANTED
|| mServiceNameResolver.isTemporary(userId)
|| mActivityTaskManagerInternal.isCallerRecents(Binder.getCallingUid())) {
return;
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 3067beb..770de09 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -80,6 +80,7 @@
":vold_aidl",
":gsiservice_aidl",
":platform-compat-config",
+ ":tethering-servicescore-srcs",
"java/com/android/server/EventLogTags.logtags",
"java/com/android/server/am/EventLogTags.logtags",
"java/com/android/server/policy/EventLogTags.logtags",
@@ -114,7 +115,6 @@
"android.hardware.contexthub-V1.0-java",
"android.hidl.manager-V1.2-java",
"dnsresolver_aidl_interface-V2-java",
- "netd_aidl_interface-java",
"netd_event_listener_interface-java",
],
}
@@ -155,3 +155,11 @@
name: "protolog.conf.json.gz",
src: ":services.core.json.gz",
}
+
+// TODO: this should be removed after tethering migration done.
+filegroup {
+ name: "servicescore-tethering-src",
+ srcs: [
+ "java/com/android/server/connectivity/MockableSystemProperties.java",
+ ],
+}
diff --git a/core/java/android/os/BatteryStatsInternal.java b/services/core/java/android/os/BatteryStatsInternal.java
similarity index 100%
rename from core/java/android/os/BatteryStatsInternal.java
rename to services/core/java/android/os/BatteryStatsInternal.java
diff --git a/services/core/java/com/android/server/AlarmManagerInternal.java b/services/core/java/com/android/server/AlarmManagerInternal.java
index 5b0de5e..0a73502 100644
--- a/services/core/java/com/android/server/AlarmManagerInternal.java
+++ b/services/core/java/com/android/server/AlarmManagerInternal.java
@@ -16,6 +16,8 @@
package com.android.server;
+import android.app.PendingIntent;
+
public interface AlarmManagerInternal {
// Some other components in the system server need to know about
// broadcast alarms currently in flight
@@ -30,4 +32,10 @@
boolean isIdling();
public void removeAlarmsForUid(int uid);
public void registerInFlightListener(InFlightListener callback);
+
+ /**
+ * Removes any alarm with the given pending intent with equality determined using
+ * {@link android.app.PendingIntent#equals(java.lang.Object) PendingIntent.equals}
+ */
+ void remove(PendingIntent rec);
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index ff0044f..e4d477a 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -154,7 +154,7 @@
static final int TICK_HISTORY_DEPTH = 10;
static final long MILLIS_IN_DAY = 24 * 60 * 60 * 1000;
- // Indices into the APP_STANDBY_MIN_DELAYS and KEYS_APP_STANDBY_DELAY arrays
+ // Indices into the KEYS_APP_STANDBY_QUOTAS array.
static final int ACTIVE_INDEX = 0;
static final int WORKING_INDEX = 1;
static final int FREQUENT_INDEX = 2;
@@ -213,7 +213,6 @@
IAlarmListener mTimeTickTrigger;
PendingIntent mDateChangeSender;
Random mRandom;
- PendingIntent.CancelListener mOperationCancelListener;
boolean mInteractive = true;
long mNonInteractiveStartTime;
long mNonInteractiveTime;
@@ -401,8 +400,6 @@
static final String KEY_LISTENER_TIMEOUT = "listener_timeout";
@VisibleForTesting
static final String KEY_MAX_ALARMS_PER_UID = "max_alarms_per_uid";
- @VisibleForTesting
- static final String KEY_APP_STANDBY_QUOTAS_ENABLED = "app_standby_quotas_enabled";
private static final String KEY_APP_STANDBY_WINDOW = "app_standby_window";
@VisibleForTesting
final String[] KEYS_APP_STANDBY_QUOTAS = {
@@ -413,15 +410,6 @@
"standby_never_quota",
};
- // Keys for specifying throttling delay based on app standby bucketing
- private final String[] KEYS_APP_STANDBY_DELAY = {
- "standby_active_delay",
- "standby_working_delay",
- "standby_frequent_delay",
- "standby_rare_delay",
- "standby_never_delay",
- };
-
private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
private static final long DEFAULT_MAX_INTERVAL = 365 * DateUtils.DAY_IN_MILLIS;
@@ -430,7 +418,6 @@
private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000;
private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000;
private static final int DEFAULT_MAX_ALARMS_PER_UID = 500;
- private static final boolean DEFAULT_APP_STANDBY_QUOTAS_ENABLED = true;
private static final long DEFAULT_APP_STANDBY_WINDOW = 60 * 60 * 1000; // 1 hr
/**
* Max number of times an app can receive alarms in {@link #APP_STANDBY_WINDOW}
@@ -442,13 +429,6 @@
1, // Rare
0 // Never
};
- private final long[] DEFAULT_APP_STANDBY_DELAYS = {
- 0, // Active
- 6 * 60_000, // Working
- 30 * 60_000, // Frequent
- 2 * 60 * 60_000, // Rare
- 10 * 24 * 60 * 60_000 // Never
- };
// Minimum futurity of a new alarm
public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
@@ -473,10 +453,7 @@
public long LISTENER_TIMEOUT = DEFAULT_LISTENER_TIMEOUT;
public int MAX_ALARMS_PER_UID = DEFAULT_MAX_ALARMS_PER_UID;
- public boolean APP_STANDBY_QUOTAS_ENABLED = DEFAULT_APP_STANDBY_QUOTAS_ENABLED;
-
public long APP_STANDBY_WINDOW = DEFAULT_APP_STANDBY_WINDOW;
- public long[] APP_STANDBY_MIN_DELAYS = new long[DEFAULT_APP_STANDBY_DELAYS.length];
public int[] APP_STANDBY_QUOTAS = new int[DEFAULT_APP_STANDBY_QUOTAS.length];
private ContentResolver mResolver;
@@ -532,16 +509,6 @@
DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT,
DEFAULT_LISTENER_TIMEOUT);
- APP_STANDBY_MIN_DELAYS[ACTIVE_INDEX] = mParser.getDurationMillis(
- KEYS_APP_STANDBY_DELAY[ACTIVE_INDEX],
- DEFAULT_APP_STANDBY_DELAYS[ACTIVE_INDEX]);
- for (int i = WORKING_INDEX; i < KEYS_APP_STANDBY_DELAY.length; i++) {
- APP_STANDBY_MIN_DELAYS[i] = mParser.getDurationMillis(KEYS_APP_STANDBY_DELAY[i],
- Math.max(APP_STANDBY_MIN_DELAYS[i - 1], DEFAULT_APP_STANDBY_DELAYS[i]));
- }
-
- APP_STANDBY_QUOTAS_ENABLED = mParser.getBoolean(KEY_APP_STANDBY_QUOTAS_ENABLED,
- DEFAULT_APP_STANDBY_QUOTAS_ENABLED);
APP_STANDBY_WINDOW = mParser.getLong(KEY_APP_STANDBY_WINDOW,
DEFAULT_APP_STANDBY_WINDOW);
@@ -614,15 +581,6 @@
pw.print(KEY_MAX_ALARMS_PER_UID); pw.print("=");
pw.println(MAX_ALARMS_PER_UID);
- for (int i = 0; i < KEYS_APP_STANDBY_DELAY.length; i++) {
- pw.print(KEYS_APP_STANDBY_DELAY[i]); pw.print("=");
- TimeUtils.formatDuration(APP_STANDBY_MIN_DELAYS[i], pw);
- pw.println();
- }
-
- pw.print(KEY_APP_STANDBY_QUOTAS_ENABLED); pw.print("=");
- pw.println(APP_STANDBY_QUOTAS_ENABLED);
-
pw.print(KEY_APP_STANDBY_WINDOW); pw.print("=");
TimeUtils.formatDuration(APP_STANDBY_WINDOW, pw);
pw.println();
@@ -1501,7 +1459,6 @@
synchronized (mLock) {
mHandler = new AlarmHandler();
- mOperationCancelListener = (intent) -> removeImpl(intent, null);
mConstants = new Constants(mHandler);
mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW);
@@ -1756,9 +1713,6 @@
} else {
maxElapsed = triggerElapsed + windowLength;
}
- if (operation != null) {
- operation.registerCancelListener(mOperationCancelListener);
- }
synchronized (mLock) {
if (DEBUG_BATCH) {
Slog.v(TAG, "set(" + operation + ") : type=" + type
@@ -1771,8 +1725,6 @@
"Maximum limit of concurrent alarms " + mConstants.MAX_ALARMS_PER_UID
+ " reached for uid: " + UserHandle.formatUid(callingUid)
+ ", callingPackage: " + callingPackage;
- mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER,
- operation).sendToTarget();
Slog.w(TAG, errorMsg);
throw new IllegalStateException(errorMsg);
}
@@ -1793,8 +1745,6 @@
if (ActivityManager.getService().isAppStartModeDisabled(callingUid, callingPackage)) {
Slog.w(TAG, "Not setting alarm from " + callingUid + ":" + a
+ " -- package not allowed to start");
- mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER,
- operation).sendToTarget();
return;
}
} catch (RemoteException e) {
@@ -1826,27 +1776,6 @@
}
/**
- * Return the minimum time that should elapse before an app in the specified bucket
- * can receive alarms again
- */
- @VisibleForTesting
- long getMinDelayForBucketLocked(int bucket) {
- // UsageStats bucket values are treated as floors of their behavioral range.
- // In other words, a bucket value between WORKING and ACTIVE is treated as
- // WORKING, not as ACTIVE. The ACTIVE and NEVER bucket apply only at specific
- // values.
- final int index;
-
- if (bucket == UsageStatsManager.STANDBY_BUCKET_NEVER) index = NEVER_INDEX;
- else if (bucket > UsageStatsManager.STANDBY_BUCKET_FREQUENT) index = RARE_INDEX;
- else if (bucket > UsageStatsManager.STANDBY_BUCKET_WORKING_SET) index = FREQUENT_INDEX;
- else if (bucket > UsageStatsManager.STANDBY_BUCKET_ACTIVE) index = WORKING_INDEX;
- else index = ACTIVE_INDEX;
-
- return mConstants.APP_STANDBY_MIN_DELAYS[index];
- }
-
- /**
* Adjusts the alarm delivery time based on the current app standby bucket.
* @param alarm The alarm to adjust
* @return true if the alarm delivery time was updated.
@@ -1872,50 +1801,34 @@
final int standbyBucket = mUsageStatsManagerInternal.getAppStandbyBucket(
sourcePackage, sourceUserId, mInjector.getElapsedRealtime());
- if (mConstants.APP_STANDBY_QUOTAS_ENABLED) {
- // Quota deferring implementation:
- final int wakeupsInWindow = mAppWakeupHistory.getTotalWakeupsInWindow(sourcePackage,
- sourceUserId);
- final int quotaForBucket = getQuotaForBucketLocked(standbyBucket);
- boolean deferred = false;
- if (wakeupsInWindow >= quotaForBucket) {
- final long minElapsed;
- if (quotaForBucket <= 0) {
- // Just keep deferring for a day till the quota changes
- minElapsed = mInjector.getElapsedRealtime() + MILLIS_IN_DAY;
- } else {
- // Suppose the quota for window was q, and the qth last delivery time for this
- // package was t(q) then the next delivery must be after t(q) + <window_size>
- final long t = mAppWakeupHistory.getLastWakeupForPackage(sourcePackage,
- sourceUserId, quotaForBucket);
- minElapsed = t + 1 + mConstants.APP_STANDBY_WINDOW;
- }
- if (alarm.expectedWhenElapsed < minElapsed) {
- alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed;
- deferred = true;
- }
+ // Quota deferring implementation:
+ final int wakeupsInWindow = mAppWakeupHistory.getTotalWakeupsInWindow(sourcePackage,
+ sourceUserId);
+ final int quotaForBucket = getQuotaForBucketLocked(standbyBucket);
+ boolean deferred = false;
+ if (wakeupsInWindow >= quotaForBucket) {
+ final long minElapsed;
+ if (quotaForBucket <= 0) {
+ // Just keep deferring for a day till the quota changes
+ minElapsed = mInjector.getElapsedRealtime() + MILLIS_IN_DAY;
+ } else {
+ // Suppose the quota for window was q, and the qth last delivery time for this
+ // package was t(q) then the next delivery must be after t(q) + <window_size>
+ final long t = mAppWakeupHistory.getLastWakeupForPackage(sourcePackage,
+ sourceUserId, quotaForBucket);
+ minElapsed = t + 1 + mConstants.APP_STANDBY_WINDOW;
}
- if (!deferred) {
- // Restore original requirements in case they were changed earlier.
- alarm.whenElapsed = alarm.expectedWhenElapsed;
- alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed;
- }
- } else {
- // Minimum delay deferring implementation:
- final long lastElapsed = mAppWakeupHistory.getLastWakeupForPackage(sourcePackage,
- sourceUserId, 1);
- if (lastElapsed > 0) {
- final long minElapsed = lastElapsed + getMinDelayForBucketLocked(standbyBucket);
- if (alarm.expectedWhenElapsed < minElapsed) {
- alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed;
- } else {
- // app is now eligible to run alarms at the originally requested window.
- // Restore original requirements in case they were changed earlier.
- alarm.whenElapsed = alarm.expectedWhenElapsed;
- alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed;
- }
+ if (alarm.expectedWhenElapsed < minElapsed) {
+ alarm.whenElapsed = alarm.maxWhenElapsed = minElapsed;
+ deferred = true;
}
}
+ if (!deferred) {
+ // Restore original requirements in case they were changed earlier.
+ alarm.whenElapsed = alarm.expectedWhenElapsed;
+ alarm.maxWhenElapsed = alarm.expectedMaxWhenElapsed;
+ }
+
return (oldWhenElapsed != alarm.whenElapsed || oldMaxWhenElapsed != alarm.maxWhenElapsed);
}
@@ -2048,6 +1961,11 @@
}
@Override
+ public void remove(PendingIntent pi) {
+ mHandler.obtainMessage(AlarmHandler.REMOVE_FOR_CANCELED, pi).sendToTarget();
+ }
+
+ @Override
public void registerInFlightListener(InFlightListener callback) {
synchronized (mLock) {
mInFlightListeners.add(callback);
@@ -2152,8 +2070,6 @@
synchronized (mLock) {
removeLocked(operation, listener);
}
- mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER,
- operation).sendToTarget();
}
@Override
@@ -4156,7 +4072,7 @@
public static final int APP_STANDBY_BUCKET_CHANGED = 5;
public static final int CHARGING_STATUS_CHANGED = 6;
public static final int REMOVE_FOR_STOPPED = 7;
- public static final int UNREGISTER_CANCEL_LISTENER = 8;
+ public static final int REMOVE_FOR_CANCELED = 8;
AlarmHandler() {
super(Looper.myLooper());
@@ -4239,10 +4155,10 @@
}
break;
- case UNREGISTER_CANCEL_LISTENER:
- final PendingIntent pi = (PendingIntent) msg.obj;
- if (pi != null) {
- pi.unregisterCancelListener(mOperationCancelListener);
+ case REMOVE_FOR_CANCELED:
+ final PendingIntent operation = (PendingIntent) msg.obj;
+ synchronized (mLock) {
+ removeLocked(operation, null);
}
break;
@@ -4446,7 +4362,8 @@
}
final class UidObserver extends IUidObserver.Stub {
- @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
+ @Override public void onUidStateChanged(int uid, int procState, long procStateSeq,
+ int capability) {
}
@Override public void onUidGone(int uid, boolean disabled) {
@@ -4721,11 +4638,6 @@
Intent.EXTRA_ALARM_COUNT, alarm.count),
mDeliveryTracker, mHandler, null,
allowWhileIdle ? mIdleOptions : null);
- if (alarm.repeatInterval == 0) {
- // Keep the listener for repeating alarms until they get cancelled
- mHandler.obtainMessage(AlarmHandler.UNREGISTER_CANCEL_LISTENER,
- alarm.operation).sendToTarget();
- }
} catch (PendingIntent.CanceledException e) {
if (alarm.repeatInterval > 0) {
// This IntentSender is no longer valid, but this
diff --git a/services/core/java/com/android/server/AppStateTracker.java b/services/core/java/com/android/server/AppStateTracker.java
index 5eff2c5..486cd5f 100644
--- a/services/core/java/com/android/server/AppStateTracker.java
+++ b/services/core/java/com/android/server/AppStateTracker.java
@@ -632,7 +632,7 @@
private final class UidObserver extends IUidObserver.Stub {
@Override
- public void onUidStateChanged(int uid, int procState, long procStateSeq) {
+ public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) {
mHandler.onUidStateChanged(uid, procState);
}
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index aeb3e7f..028d412 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.Uri;
@@ -40,11 +41,13 @@
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
+import android.service.dropbox.DropBoxManagerServiceDumpProto;
import android.text.TextUtils;
import android.text.format.TimeMigrationUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -65,6 +68,7 @@
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.zip.GZIPOutputStream;
@@ -85,6 +89,9 @@
private static final boolean PROFILE_DUMP = false;
+ // Max number of bytes of a dropbox entry to write into protobuf.
+ private static final int PROTO_MAX_DATA_BYTES = 256 * 1024;
+
// TODO: This implementation currently uses one file per entry, which is
// inefficient for smallish entries -- consider using a single queue file
// per tag (or even globally) instead.
@@ -464,6 +471,14 @@
}
private boolean checkPermission(int callingUid, String callingPackage) {
+ // If callers have this permission, then we don't need to check
+ // USAGE_STATS, because they are part of the system and have agreed to
+ // check USAGE_STATS before passing the data along.
+ if (getContext().checkCallingPermission(android.Manifest.permission.PEEK_DROPBOX_DATA)
+ == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+
// Callers always need this permission
getContext().enforceCallingOrSelfPermission(
android.Manifest.permission.READ_LOGS, TAG);
@@ -547,18 +562,22 @@
StringBuilder out = new StringBuilder();
boolean doPrint = false, doFile = false;
+ boolean dumpProto = false;
ArrayList<String> searchArgs = new ArrayList<String>();
for (int i = 0; args != null && i < args.length; i++) {
if (args[i].equals("-p") || args[i].equals("--print")) {
doPrint = true;
} else if (args[i].equals("-f") || args[i].equals("--file")) {
doFile = true;
+ } else if (args[i].equals("--proto")) {
+ dumpProto = true;
} else if (args[i].equals("-h") || args[i].equals("--help")) {
pw.println("Dropbox (dropbox) dump options:");
pw.println(" [-h|--help] [-p|--print] [-f|--file] [timestamp]");
pw.println(" -h|--help: print this help");
pw.println(" -p|--print: print full contents of each entry");
pw.println(" -f|--file: print path of each entry's file");
+ pw.println(" --proto: dump data to proto");
pw.println(" [timestamp] optionally filters to only those entries.");
return;
} else if (args[i].startsWith("-")) {
@@ -568,6 +587,11 @@
}
}
+ if (dumpProto) {
+ dumpProtoLocked(fd, searchArgs);
+ return;
+ }
+
out.append("Drop box contents: ").append(mAllFiles.contents.size()).append(" entries\n");
out.append("Max entries: ").append(mMaxFiles).append("\n");
@@ -581,19 +605,15 @@
out.append("\n");
}
- int numFound = 0, numArgs = searchArgs.size();
+ int numFound = 0;
out.append("\n");
for (EntryFile entry : mAllFiles.contents) {
- String date = TimeMigrationUtils.formatMillisWithFixedFormat(entry.timestampMillis);
- boolean match = true;
- for (int i = 0; i < numArgs && match; i++) {
- String arg = searchArgs.get(i);
- match = (date.contains(arg) || arg.equals(entry.tag));
- }
- if (!match) continue;
+ if (!matchEntry(entry, searchArgs)) continue;
numFound++;
if (doPrint) out.append("========================================\n");
+
+ String date = TimeMigrationUtils.formatMillisWithFixedFormat(entry.timestampMillis);
out.append(date).append(" ").append(entry.tag == null ? "(no tag)" : entry.tag);
final File file = entry.getFile(mDropBoxDir);
@@ -679,6 +699,55 @@
if (PROFILE_DUMP) Debug.stopMethodTracing();
}
+ private boolean matchEntry(EntryFile entry, ArrayList<String> searchArgs) {
+ String date = TimeMigrationUtils.formatMillisWithFixedFormat(entry.timestampMillis);
+ boolean match = true;
+ int numArgs = searchArgs.size();
+ for (int i = 0; i < numArgs && match; i++) {
+ String arg = searchArgs.get(i);
+ match = (date.contains(arg) || arg.equals(entry.tag));
+ }
+ return match;
+ }
+
+ private void dumpProtoLocked(FileDescriptor fd, ArrayList<String> searchArgs) {
+ final ProtoOutputStream proto = new ProtoOutputStream(fd);
+
+ for (EntryFile entry : mAllFiles.contents) {
+ if (!matchEntry(entry, searchArgs)) continue;
+
+ final File file = entry.getFile(mDropBoxDir);
+ if ((file == null) || ((entry.flags & DropBoxManager.IS_EMPTY) != 0)) {
+ continue;
+ }
+
+ final long bToken = proto.start(DropBoxManagerServiceDumpProto.ENTRIES);
+ proto.write(DropBoxManagerServiceDumpProto.Entry.TIME_MS, entry.timestampMillis);
+ try (
+ DropBoxManager.Entry dbe = new DropBoxManager.Entry(
+ entry.tag, entry.timestampMillis, file, entry.flags);
+ InputStream is = dbe.getInputStream();
+ ) {
+ if (is != null) {
+ byte[] buf = new byte[PROTO_MAX_DATA_BYTES];
+ int readBytes = 0;
+ int n = 0;
+ while (n >= 0 && (readBytes += n) < PROTO_MAX_DATA_BYTES) {
+ n = is.read(buf, readBytes, PROTO_MAX_DATA_BYTES - readBytes);
+ }
+ proto.write(DropBoxManagerServiceDumpProto.Entry.DATA,
+ Arrays.copyOf(buf, readBytes));
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Can't read: " + file, e);
+ }
+
+ proto.end(bToken);
+ }
+
+ proto.flush();
+ }
+
///////////////////////////////////////////////////////////////////////////
/** Chronologically sorted list of {@link EntryFile} */
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 0a63bf8..e1f6597 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -43,7 +43,6 @@
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.content.res.Resources;
-import android.database.ContentObserver;
import android.hardware.location.ActivityRecognitionHardware;
import android.location.Address;
import android.location.Criteria;
@@ -79,7 +78,6 @@
import android.provider.Settings;
import android.stats.location.LocationStatsEnums;
import android.text.TextUtils;
-import android.util.ArraySet;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
@@ -99,12 +97,12 @@
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceManager;
import com.android.server.location.GeofenceProxy;
-import com.android.server.location.LocationBlacklist;
import com.android.server.location.LocationFudger;
import com.android.server.location.LocationProviderProxy;
import com.android.server.location.LocationRequestStatistics;
import com.android.server.location.LocationRequestStatistics.PackageProviderKey;
import com.android.server.location.LocationRequestStatistics.PackageStatistics;
+import com.android.server.location.LocationSettingsStore;
import com.android.server.location.MockProvider;
import com.android.server.location.PassiveProvider;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
@@ -128,6 +126,32 @@
* updates and alerts.
*/
public class LocationManagerService extends ILocationManager.Stub {
+
+ /**
+ * Controls lifecycle of LocationManagerService.
+ */
+ public static class Lifecycle extends SystemService {
+
+ private LocationManagerService mService;
+
+ public Lifecycle(Context context) {
+ super(context);
+ mService = new LocationManagerService(context);
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(Context.LOCATION_SERVICE, mService);
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
+ mService.systemRunning();
+ }
+ }
+ }
+
private static final String TAG = "LocationManagerService";
public static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
@@ -157,13 +181,6 @@
private static final int FOREGROUND_IMPORTANCE_CUTOFF
= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
- // default background throttling interval if not overriden in settings
- private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
-
- // Default value for maximum age of last location returned to applications with foreground-only
- // location permissions.
- private static final long DEFAULT_LAST_LOCATION_MAX_AGE_MS = 20 * 60 * 1000;
-
// Location Providers may sometimes deliver location updates
// slightly faster that requested - provide grace period so
// we don't unnecessarily filter events that are otherwise on
@@ -182,13 +199,14 @@
private ActivityManager mActivityManager;
private UserManager mUserManager;
+ private LocationSettingsStore mSettingsStore;
+
private GeofenceManager mGeofenceManager;
private LocationFudger mLocationFudger;
private GeocoderProxy mGeocodeProvider;
@Nullable
private GnssManagerService mGnssManagerService;
private PassiveProvider mPassiveProvider; // track passive provider for special cases
- private LocationBlacklist mBlacklist;
@GuardedBy("mLock")
private String mExtraLocationControllerPackage;
private boolean mExtraLocationControllerPackageEnabled;
@@ -219,10 +237,6 @@
private final HashMap<String, Location> mLastLocationCoarseInterval =
new HashMap<>();
- private final ArraySet<String> mBackgroundThrottlePackageWhitelist = new ArraySet<>();
-
- private final ArraySet<String> mIgnoreSettingsPackageWhitelist = new ArraySet<>();
-
// current active user on the device - other users are denied location data
private int mCurrentUserId = UserHandle.USER_SYSTEM;
private int[] mCurrentUserProfiles = new int[]{UserHandle.USER_SYSTEM};
@@ -234,8 +248,7 @@
@GuardedBy("mLock")
private final LocationUsageLogger mLocationUsageLogger;
- public LocationManagerService(Context context) {
- super();
+ private LocationManagerService(Context context) {
mContext = context;
mHandler = FgThread.getHandler();
mLocationUsageLogger = new LocationUsageLogger();
@@ -254,7 +267,7 @@
// most startup is deferred until systemRunning()
}
- public void systemRunning() {
+ private void systemRunning() {
synchronized (mLock) {
initializeLocked();
}
@@ -262,16 +275,19 @@
@GuardedBy("mLock")
private void initializeLocked() {
- mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
mPackageManager = mContext.getPackageManager();
- mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mAppOps = mContext.getSystemService(AppOpsManager.class);
+ mPowerManager = mContext.getSystemService(PowerManager.class);
+ mActivityManager = mContext.getSystemService(ActivityManager.class);
+ mUserManager = mContext.getSystemService(UserManager.class);
+
+ mSettingsStore = new LocationSettingsStore(mContext, mHandler);
mLocationFudger = new LocationFudger(mContext, mHandler);
- mBlacklist = new LocationBlacklist(mContext, mHandler);
- mBlacklist.init();
- mGeofenceManager = new GeofenceManager(mContext, mBlacklist);
+ mGeofenceManager = new GeofenceManager(mContext, mSettingsStore);
+
+ PowerManagerInternal localPowerManager =
+ LocalServices.getService(PowerManagerInternal.class);
// prepare providers
initializeProvidersLocked();
@@ -302,7 +318,6 @@
}
});
});
-
mActivityManager.addOnUidImportanceListener(
(uid, importance) -> {
// listener invoked on ui thread, move to our thread to reduce risk of blocking
@@ -314,63 +329,7 @@
});
},
FOREGROUND_IMPORTANCE_CUTOFF);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.LOCATION_MODE), true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onLocationModeChangedLocked(true);
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onProviderAllowedChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onBackgroundThrottleIntervalChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onBackgroundThrottleWhitelistChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- mContext.getContentResolver().registerContentObserver(
- Settings.Global.getUriFor(
- Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- onIgnoreSettingsWhitelistChangedLocked();
- }
- }
- }, UserHandle.USER_ALL);
- PowerManagerInternal localPowerManager =
- LocalServices.getService(PowerManagerInternal.class);
+
localPowerManager.registerLowPowerModeObserver(ServiceType.LOCATION,
state -> {
// listener invoked on ui thread, move to our thread to reduce risk of blocking
@@ -381,6 +340,33 @@
}
});
});
+ mBatterySaverMode = mPowerManager.getLocationPowerSaveMode();
+
+ mSettingsStore.addOnLocationEnabledChangedListener(() -> {
+ synchronized (mLock) {
+ onLocationModeChangedLocked(true);
+ }
+ });
+ mSettingsStore.addOnLocationProvidersAllowedChangedListener(() -> {
+ synchronized (mLock) {
+ onProviderAllowedChangedLocked();
+ }
+ });
+ mSettingsStore.addOnBackgroundThrottleIntervalChangedListener(() -> {
+ synchronized (mLock) {
+ onBackgroundThrottleIntervalChangedLocked();
+ }
+ });
+ mSettingsStore.addOnBackgroundThrottlePackageWhitelistChangedListener(() -> {
+ synchronized (mLock) {
+ onBackgroundThrottleWhitelistChangedLocked();
+ }
+ });
+ mSettingsStore.addOnIgnoreSettingsPackageWhitelistChangedListener(() -> {
+ synchronized (mLock) {
+ onIgnoreSettingsWhitelistChangedLocked();
+ }
+ });
new PackageMonitor() {
@Override
@@ -428,11 +414,6 @@
// provider initialization, and propagates changes until a steady state is reached
mCurrentUserId = UserHandle.USER_NULL;
onUserChangedLocked(ActivityManager.getCurrentUser());
-
- // initialize in-memory settings values
- onBackgroundThrottleWhitelistChangedLocked();
- onIgnoreSettingsWhitelistChangedLocked();
- onBatterySaverModeChangedLocked(mPowerManager.getLocationPowerSaveMode());
}
@GuardedBy("mLock")
@@ -454,6 +435,10 @@
@GuardedBy("mLock")
private void onBatterySaverModeChangedLocked(int newLocationMode) {
+ if (mBatterySaverMode == newLocationMode) {
+ return;
+ }
+
if (D) {
Slog.d(TAG,
"Battery Saver location mode changed from "
@@ -461,11 +446,8 @@
+ locationPowerSaveModeToString(newLocationMode));
}
- if (mBatterySaverMode == newLocationMode) {
- return;
- }
-
mBatterySaverMode = newLocationMode;
+
for (LocationProvider p : mProviders) {
applyRequirementsLocked(p);
}
@@ -563,17 +545,6 @@
@GuardedBy("mLock")
private void onBackgroundThrottleWhitelistChangedLocked() {
- mBackgroundThrottlePackageWhitelist.clear();
- mBackgroundThrottlePackageWhitelist.addAll(
- SystemConfig.getInstance().getAllowUnthrottledLocation());
-
- String setting = Settings.Global.getString(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST);
- if (!TextUtils.isEmpty(setting)) {
- mBackgroundThrottlePackageWhitelist.addAll(Arrays.asList(setting.split(",")));
- }
-
for (LocationProvider p : mProviders) {
applyRequirementsLocked(p);
}
@@ -581,17 +552,6 @@
@GuardedBy("lock")
private void onIgnoreSettingsWhitelistChangedLocked() {
- mIgnoreSettingsPackageWhitelist.clear();
- mIgnoreSettingsPackageWhitelist.addAll(
- SystemConfig.getInstance().getAllowIgnoreLocationSettings());
-
- String setting = Settings.Global.getString(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST);
- if (!TextUtils.isEmpty(setting)) {
- mIgnoreSettingsPackageWhitelist.addAll(Arrays.asList(setting.split(",")));
- }
-
for (LocationProvider p : mProviders) {
applyRequirementsLocked(p);
}
@@ -834,8 +794,6 @@
mCurrentUserId = userId;
onUserProfilesChangedLocked();
- mBlacklist.switchUser(userId);
-
// if the user changes, per-user settings may also have changed
onLocationModeChangedLocked(false);
onProviderAllowedChangedLocked();
@@ -1058,11 +1016,8 @@
@GuardedBy("mLock")
public void onAllowedChangedLocked() {
if (mIsManagedBySettings) {
- String allowedProviders = Settings.Secure.getStringForUser(
- mContext.getContentResolver(),
- Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
- mCurrentUserId);
- boolean allowed = TextUtils.delimitedStringContains(allowedProviders, ',', mName);
+ boolean allowed = mSettingsStore.getLocationProvidersAllowed(
+ mCurrentUserId).contains(mName);
if (allowed == mAllowed) {
return;
@@ -1453,6 +1408,16 @@
return true;
}
+ public void callRemovedLocked() {
+ if (mListener != null) {
+ try {
+ mListener.onRemoved();
+ } catch (RemoteException e) {
+ // doesn't matter
+ }
+ }
+ }
+
@Override
public void binderDied() {
if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
@@ -1874,10 +1839,7 @@
long identity = Binder.clearCallingIdentity();
try {
- backgroundThrottleInterval = Settings.Global.getLong(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
- DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
+ backgroundThrottleInterval = mSettingsStore.getBackgroundThrottleIntervalMs();
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -1997,16 +1959,12 @@
@Override
public String[] getBackgroundThrottlingWhitelist() {
- synchronized (mLock) {
- return mBackgroundThrottlePackageWhitelist.toArray(new String[0]);
- }
+ return mSettingsStore.getBackgroundThrottlePackageWhitelist().toArray(new String[0]);
}
@Override
public String[] getIgnoreSettingsWhitelist() {
- synchronized (mLock) {
- return mIgnoreSettingsPackageWhitelist.toArray(new String[0]);
- }
+ return mSettingsStore.getIgnoreSettingsPackageWhitelist().toArray(new String[0]);
}
@GuardedBy("mLock")
@@ -2015,7 +1973,8 @@
return true;
}
- if (mBackgroundThrottlePackageWhitelist.contains(callerIdentity.mPackageName)) {
+ if (mSettingsStore.getBackgroundThrottlePackageWhitelist().contains(
+ callerIdentity.mPackageName)) {
return true;
}
@@ -2029,7 +1988,7 @@
return false;
}
- if (mIgnoreSettingsPackageWhitelist.contains(
+ if (mSettingsStore.getIgnoreSettingsPackageWhitelist().contains(
record.mReceiver.mCallerIdentity.mPackageName)) {
return true;
}
@@ -2046,11 +2005,13 @@
private boolean mIsForegroundUid;
private Location mLastFixBroadcast;
private Throwable mStackTrace; // for debugging only
+ private long mExpirationRealtimeMs;
/**
* Note: must be constructed with lock held.
*/
private UpdateRecord(String provider, LocationRequest request, Receiver receiver) {
+ mExpirationRealtimeMs = request.getExpirationRealtimeMs(SystemClock.elapsedRealtime());
mProvider = provider;
mRealRequest = request;
mRequest = request;
@@ -2425,7 +2386,8 @@
final int uid = Binder.getCallingUid();
final long identity = Binder.clearCallingIdentity();
try {
- if (mBlacklist.isBlacklisted(packageName)) {
+ if (mSettingsStore.isLocationPackageBlacklisted(UserHandle.getUserId(uid),
+ packageName)) {
if (D) {
Log.d(TAG, "not returning last loc for blacklisted app: "
+ packageName);
@@ -2466,10 +2428,7 @@
String op = resolutionLevelToOpStr(allowedResolutionLevel);
long locationAgeMs = TimeUnit.NANOSECONDS.toMillis(
SystemClock.elapsedRealtime() - location.getElapsedRealtimeNanos());
- if ((locationAgeMs > Settings.Global.getLong(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
- DEFAULT_LAST_LOCATION_MAX_AGE_MS))
+ if (locationAgeMs > mSettingsStore.getMaxLastLocationAgeMs()
&& (mAppOps.unsafeCheckOp(op, uid, packageName)
== AppOpsManager.MODE_FOREGROUND)) {
return null;
@@ -2528,11 +2487,7 @@
boolean foreground = LocationManagerServiceUtils.isImportanceForeground(
mActivityManager.getPackageImportance(packageName));
if (!foreground) {
- long backgroundThrottleIntervalMs = Settings.Global.getLong(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
- DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
- if (locationAgeMs < backgroundThrottleIntervalMs) {
+ if (locationAgeMs < mSettingsStore.getBackgroundThrottleIntervalMs()) {
// not allowed to request new locations, so we can't return anything
return false;
}
@@ -2863,11 +2818,7 @@
long identity = Binder.clearCallingIdentity();
try {
- return Settings.Secure.getIntForUser(
- mContext.getContentResolver(),
- Settings.Secure.LOCATION_MODE,
- Settings.Secure.LOCATION_MODE_OFF,
- userId) != Settings.Secure.LOCATION_MODE_OFF;
+ return mSettingsStore.isLocationEnabled(userId);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2922,7 +2873,7 @@
}
// Check whether the expiry date has passed
- return record.mRealRequest.getExpireAt() >= now;
+ return record.mExpirationRealtimeMs >= now;
}
@GuardedBy("mLock")
@@ -3003,7 +2954,8 @@
continue;
}
- if (mBlacklist.isBlacklisted(receiver.mCallerIdentity.mPackageName)) {
+ if (mSettingsStore.isLocationPackageBlacklisted(receiverUserId,
+ receiver.mCallerIdentity.mPackageName)) {
if (D) {
Log.d(TAG, "skipping loc update for blacklisted app: " +
receiver.mCallerIdentity.mPackageName);
@@ -3053,7 +3005,9 @@
}
// track expired records
- if (r.mRealRequest.getNumUpdates() <= 0 || r.mRealRequest.getExpireAt() < now) {
+ if (r.mRealRequest.getNumUpdates() <= 0 || r.mExpirationRealtimeMs < now) {
+ // notify the client it can remove this listener
+ r.mReceiver.callRemovedLocked();
if (deadUpdateRecords == null) {
deadUpdateRecords = new ArrayList<>();
}
@@ -3343,33 +3297,11 @@
ipw.decreaseIndent();
}
- if (mBlacklist != null) {
- mBlacklist.dump(ipw);
- }
-
if (mExtraLocationControllerPackage != null) {
ipw.println("Location Controller Extra Package: " + mExtraLocationControllerPackage
+ (mExtraLocationControllerPackageEnabled ? " [enabled]" : "[disabled]"));
}
- if (!mBackgroundThrottlePackageWhitelist.isEmpty()) {
- ipw.println("Throttling Whitelisted Packages:");
- ipw.increaseIndent();
- for (String packageName : mBackgroundThrottlePackageWhitelist) {
- ipw.println(packageName);
- }
- ipw.decreaseIndent();
- }
-
- if (!mIgnoreSettingsPackageWhitelist.isEmpty()) {
- ipw.println("Bypass Whitelisted Packages:");
- ipw.increaseIndent();
- for (String packageName : mIgnoreSettingsPackageWhitelist) {
- ipw.println(packageName);
- }
- ipw.decreaseIndent();
- }
-
if (mLocationFudger != null) {
ipw.println("Location Fudger:");
ipw.increaseIndent();
@@ -3377,6 +3309,8 @@
ipw.decreaseIndent();
}
+ mSettingsStore.dump(fd, pw, args);
+
ipw.println("Location Providers:");
ipw.increaseIndent();
for (LocationProvider provider : mProviders) {
diff --git a/services/core/java/com/android/server/NetworkScorerAppManager.java b/services/core/java/com/android/server/NetworkScorerAppManager.java
index bfd4247..3bcb36f 100644
--- a/services/core/java/com/android/server/NetworkScorerAppManager.java
+++ b/services/core/java/com/android/server/NetworkScorerAppManager.java
@@ -18,10 +18,10 @@
import android.Manifest.permission;
import android.annotation.Nullable;
-import android.app.AppOpsManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.PermissionChecker;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
@@ -210,14 +210,9 @@
}
private boolean canAccessLocation(int uid, String packageName) {
- final PackageManager pm = mContext.getPackageManager();
- final AppOpsManager appOpsManager =
- (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
- return isLocationModeEnabled()
- && pm.checkPermission(permission.ACCESS_COARSE_LOCATION, packageName)
- == PackageManager.PERMISSION_GRANTED
- && appOpsManager.noteOp(AppOpsManager.OP_COARSE_LOCATION, uid, packageName)
- == AppOpsManager.MODE_ALLOWED;
+ return isLocationModeEnabled() && PermissionChecker.checkPermissionForPreflight(mContext,
+ permission.ACCESS_COARSE_LOCATION, PermissionChecker.PID_UNKNOWN, uid, packageName)
+ == PermissionChecker.PERMISSION_GRANTED;
}
private boolean isLocationModeEnabled() {
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index 49ef164..d5f7956 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -333,8 +333,8 @@
}
@Override
- public void onUidStateChanged(int uid, int procState, long procStateSeq)
- throws RemoteException {
+ public void onUidStateChanged(int uid, int procState, long procStateSeq,
+ int capability) throws RemoteException {
}
@Override
diff --git a/services/core/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java
index e3dc3b7..7f51aa9 100644
--- a/services/core/java/com/android/server/ServiceWatcher.java
+++ b/services/core/java/com/android/server/ServiceWatcher.java
@@ -51,6 +51,8 @@
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* Find the best Service, and bind to it.
@@ -64,6 +66,7 @@
public static final String EXTRA_SERVICE_VERSION = "serviceVersion";
public static final String EXTRA_SERVICE_IS_MULTIUSER = "serviceIsMultiuser";
+ private static final long BLOCKING_BINDER_TIMEOUT_MS = 30 * 1000;
/** Function to run on binder interface. */
public interface BinderRunner {
@@ -402,7 +405,7 @@
return defaultValue;
}
});
- } catch (InterruptedException e) {
+ } catch (InterruptedException | TimeoutException e) {
return defaultValue;
}
}
@@ -439,7 +442,8 @@
}
}
- private <T> T runOnHandlerBlocking(Callable<T> c) throws InterruptedException {
+ private <T> T runOnHandlerBlocking(Callable<T> c)
+ throws InterruptedException, TimeoutException {
if (Looper.myLooper() == mHandler.getLooper()) {
try {
return c.call();
@@ -451,7 +455,12 @@
FutureTask<T> task = new FutureTask<>(c);
mHandler.post(task);
try {
- return task.get();
+ // timeout will unblock callers, in particular if the caller is a binder thread to
+ // help reduce binder contention. this will still result in blocking the handler
+ // thread which may result in ANRs, but should make problems slightly more rare.
+ // the underlying solution is simply not to use this API at all, but that would
+ // require large refactors to very legacy code.
+ return task.get(BLOCKING_BINDER_TIMEOUT_MS, TimeUnit.MILLISECONDS);
} catch (ExecutionException e) {
// Function cannot throw exception, this should never happen
throw new IllegalStateException(e);
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index d622fb4..b8acd7a 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -174,7 +174,8 @@
static native long vibratorGetCapabilities();
private final IUidObserver mUidObserver = new IUidObserver.Stub() {
- @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
+ @Override public void onUidStateChanged(int uid, int procState, long procStateSeq,
+ int capability) {
mProcStatesCache.put(uid, procState);
}
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 4f54e64..b5cab1f 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -3248,7 +3248,7 @@
UserAccounts accounts = getUserAccounts(userId);
logRecordWithUid(
accounts, AccountsDb.DEBUG_ACTION_CALLED_ACCOUNT_ADD, AccountsDb.TABLE_ACCOUNTS,
- userId);
+ uid);
new Session(accounts, response, accountType, expectActivityLaunch,
true /* stripAuthTokenFromResult */, null /* accountName */,
false /* authDetailsRequired */, true /* updateLastAuthenticationTime */) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 11cfe12..a6d216fe 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -139,6 +139,7 @@
import android.Manifest;
import android.Manifest.permission;
+import android.annotation.BroadcastBehavior;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -299,10 +300,8 @@
import android.view.WindowManager;
import android.view.autofill.AutofillManagerInternal;
-import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.app.DumpHeapActivity;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.ProcessMap;
@@ -503,6 +502,41 @@
static final int PERSISTENT_MASK =
ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
+ // Intent sent when remote bugreport collection has been completed
+ private static final String INTENT_REMOTE_BUGREPORT_FINISHED =
+ "com.android.internal.intent.action.REMOTE_BUGREPORT_FINISHED";
+
+ /**
+ * Broadcast sent when heap dump collection has been completed.
+ */
+ @BroadcastBehavior(includeBackground = true, protectedBroadcast = true)
+ private static final String ACTION_HEAP_DUMP_FINISHED =
+ "com.android.internal.intent.action.HEAP_DUMP_FINISHED";
+
+ /**
+ * The process we are reporting
+ */
+ private static final String EXTRA_HEAP_DUMP_PROCESS_NAME =
+ "com.android.internal.extra.heap_dump.PROCESS_NAME";
+
+ /**
+ * The size limit the process reached.
+ */
+ private static final String EXTRA_HEAP_DUMP_SIZE_BYTES =
+ "com.android.internal.extra.heap_dump.SIZE_BYTES";
+
+ /**
+ * Whether the user initiated the dump or not.
+ */
+ private static final String EXTRA_HEAP_DUMP_IS_USER_INITIATED =
+ "com.android.internal.extra.heap_dump.IS_USER_INITIATED";
+
+ /**
+ * Optional name of package to directly launch.
+ */
+ private static final String EXTRA_HEAP_DUMP_REPORT_PACKAGE =
+ "com.android.internal.extra.heap_dump.REPORT_PACKAGE";
+
// If set, we will push process association information in to procstats.
static final boolean TRACK_PROCSTATS_ASSOCIATIONS = true;
@@ -1332,7 +1366,7 @@
int mProfileType = 0;
final ProcessMap<Pair<Long, String>> mMemWatchProcesses = new ProcessMap<>();
String mMemWatchDumpProcName;
- String mMemWatchDumpFile;
+ Uri mMemWatchDumpUri;
int mMemWatchDumpPid;
int mMemWatchDumpUid;
private boolean mMemWatchIsUserInitiated;
@@ -1344,10 +1378,12 @@
static final class ProcessChangeItem {
static final int CHANGE_ACTIVITIES = 1<<0;
static final int CHANGE_FOREGROUND_SERVICES = 1<<1;
+ static final int CHANGE_CAPABILITY = 1<<2;
int changes;
int uid;
int pid;
int processState;
+ int capability;
boolean foregroundActivities;
int foregroundServiceTypes;
}
@@ -1519,7 +1555,7 @@
static final int UPDATE_TIME_PREFERENCE_MSG = 41;
static final int NOTIFY_CLEARTEXT_NETWORK_MSG = 49;
static final int POST_DUMP_HEAP_NOTIFICATION_MSG = 50;
- static final int DELETE_DUMPHEAP_MSG = 51;
+ static final int ABORT_DUMPHEAP_MSG = 51;
static final int DISPATCH_UIDS_CHANGED_UI_MSG = 53;
static final int SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG = 56;
static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG = 57;
@@ -1788,11 +1824,7 @@
final boolean isUserInitiated;
synchronized (ActivityManagerService.this) {
uid = mMemWatchDumpUid;
- if (uid == SYSTEM_UID) {
- procName = mContext.getString(R.string.android_system_label);
- } else {
- procName = mMemWatchDumpProcName;
- }
+ procName = mMemWatchDumpProcName;
Pair<Long, String> val = mMemWatchProcesses.get(procName, uid);
if (val == null) {
val = mMemWatchProcesses.get(procName, 0);
@@ -1805,6 +1837,11 @@
reportPackage = null;
}
isUserInitiated = mMemWatchIsUserInitiated;
+
+ mMemWatchDumpUri = null;
+ mMemWatchDumpProcName = null;
+ mMemWatchDumpPid = -1;
+ mMemWatchDumpUid = -1;
}
if (procName == null) {
return;
@@ -1813,65 +1850,29 @@
if (DEBUG_PSS) Slog.d(TAG_PSS,
"Showing dump heap notification from " + procName + "/" + uid);
- INotificationManager inm = NotificationManager.getService();
- if (inm == null) {
- return;
- }
+ Intent dumpFinishedIntent = new Intent(ACTION_HEAP_DUMP_FINISHED);
+ // Send this only to the Shell package.
+ dumpFinishedIntent.setPackage("com.android.shell");
+ dumpFinishedIntent.putExtra(Intent.EXTRA_UID, uid);
+ dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_IS_USER_INITIATED, isUserInitiated);
+ dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_SIZE_BYTES, memLimit);
+ dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_REPORT_PACKAGE, reportPackage);
+ dumpFinishedIntent.putExtra(EXTRA_HEAP_DUMP_PROCESS_NAME, procName);
- final int titleId = isUserInitiated
- ? R.string.dump_heap_ready_notification : R.string.dump_heap_notification;
- String text = mContext.getString(titleId, procName);
-
- Intent deleteIntent = new Intent();
- deleteIntent.setAction(DumpHeapActivity.ACTION_DELETE_DUMPHEAP);
- Intent intent = new Intent();
- intent.setClassName("android", DumpHeapActivity.class.getName());
- intent.putExtra(DumpHeapActivity.KEY_PROCESS, procName);
- intent.putExtra(DumpHeapActivity.KEY_SIZE, memLimit);
- intent.putExtra(DumpHeapActivity.KEY_IS_USER_INITIATED, isUserInitiated);
- intent.putExtra(DumpHeapActivity.KEY_IS_SYSTEM_PROCESS, uid == SYSTEM_UID);
- if (reportPackage != null) {
- intent.putExtra(DumpHeapActivity.KEY_DIRECT_LAUNCH, reportPackage);
- }
- int userId = UserHandle.getUserId(uid);
- Notification notification =
- new Notification.Builder(mContext, SystemNotificationChannels.DEVELOPER)
- .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
- .setAutoCancel(true)
- .setTicker(text)
- .setColor(mContext.getColor(
- com.android.internal.R.color.system_notification_accent_color))
- .setContentTitle(text)
- .setContentText(
- mContext.getText(R.string.dump_heap_notification_detail))
- .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0,
- intent, PendingIntent.FLAG_CANCEL_CURRENT, null,
- new UserHandle(userId)))
- .setDeleteIntent(PendingIntent.getBroadcastAsUser(mContext, 0,
- deleteIntent, 0, UserHandle.SYSTEM))
- .build();
-
- try {
- inm.enqueueNotificationWithTag("android", "android", null,
- SystemMessage.NOTE_DUMP_HEAP_NOTIFICATION,
- notification, userId);
- } catch (RuntimeException e) {
- Slog.w(ActivityManagerService.TAG,
- "Error showing notification for dump heap", e);
- } catch (RemoteException e) {
- }
+ mContext.sendBroadcastAsUser(dumpFinishedIntent,
+ UserHandle.getUserHandleForUid(uid));
} break;
- case DELETE_DUMPHEAP_MSG: {
- revokeUriPermission(ActivityThread.currentActivityThread().getApplicationThread(),
- null, DumpHeapActivity.JAVA_URI,
- Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
- UserHandle.myUserId());
- synchronized (ActivityManagerService.this) {
- mMemWatchDumpFile = null;
- mMemWatchDumpProcName = null;
- mMemWatchDumpPid = -1;
- mMemWatchDumpUid = -1;
+ case ABORT_DUMPHEAP_MSG: {
+ String procName = (String) msg.obj;
+ if (procName != null) {
+ synchronized (ActivityManagerService.this) {
+ if (procName.equals(mMemWatchDumpProcName)) {
+ mMemWatchDumpProcName = null;
+ mMemWatchDumpUri = null;
+ mMemWatchDumpPid = -1;
+ mMemWatchDumpUid = -1;
+ }
+ }
}
} break;
case SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG: {
@@ -3337,6 +3338,7 @@
validateUid.idle = false;
}
validateUid.setCurProcState(validateUid.setProcState = item.processState);
+ validateUid.curCapability = validateUid.setCapability = item.capability;
validateUid.lastDispatchedProcStateSeq = item.procStateSeq;
}
}
@@ -3402,7 +3404,7 @@
if ((reg.which & ActivityManager.UID_OBSERVER_PROCSTATE) != 0) {
if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
"UID CHANGED uid=" + item.uid
- + ": " + item.processState);
+ + ": " + item.processState + ": " + item.capability);
boolean doReport = true;
if (reg.cutpoint >= ActivityManager.MIN_PROCESS_STATE) {
final int lastState = reg.lastProcStates.get(item.uid,
@@ -3420,7 +3422,7 @@
reg.lastProcStates.put(item.uid, item.processState);
}
observer.onUidStateChanged(item.uid, item.processState,
- item.procStateSeq);
+ item.procStateSeq, item.capability);
}
}
}
@@ -5245,17 +5247,6 @@
}
}, pkgFilter);
- IntentFilter dumpheapFilter = new IntentFilter();
- dumpheapFilter.addAction(DumpHeapActivity.ACTION_DELETE_DUMPHEAP);
- mContext.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final long delay = intent.getBooleanExtra(
- DumpHeapActivity.EXTRA_DELAY_DELETE, false) ? 5 * 60 * 1000 : 0;
- mHandler.sendEmptyMessageDelayed(DELETE_DUMPHEAP_MSG, delay);
- }
- }, dumpheapFilter);
-
// Inform checkpointing systems of success
try {
// This line is needed to CTS test for the correct exception handling
@@ -7758,7 +7749,7 @@
holder = getContentProviderExternalUnchecked(name, null, callingUid,
"*checkContentProviderUriPermission*", userId);
if (holder != null) {
- return holder.provider.checkUriPermission(null, uri, callingUid, modeFlags);
+ return holder.provider.checkUriPermission(null, null, uri, callingUid, modeFlags);
}
} catch (RemoteException e) {
Log.w(TAG, "Content provider dead retrieving " + uri, e);
@@ -7855,10 +7846,18 @@
false /* mountExtStorageFull */, abiOverride);
}
- // TODO: Move to ProcessList?
@GuardedBy("this")
final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
boolean disableHiddenApiChecks, boolean mountExtStorageFull, String abiOverride) {
+ return addAppLocked(info, customProcess, isolated, disableHiddenApiChecks,
+ false /* disableTestApiChecks */, mountExtStorageFull, abiOverride);
+ }
+
+ // TODO: Move to ProcessList?
+ @GuardedBy("this")
+ final ProcessRecord addAppLocked(ApplicationInfo info, String customProcess, boolean isolated,
+ boolean disableHiddenApiChecks, boolean disableTestApiChecks,
+ boolean mountExtStorageFull, String abiOverride) {
ProcessRecord app;
if (!isolated) {
app = getProcessRecordLocked(customProcess != null ? customProcess : info.processName,
@@ -7893,7 +7892,7 @@
mPersistentStartingProcesses.add(app);
mProcessList.startProcessLocked(app, new HostingRecord("added application",
customProcess != null ? customProcess : app.processName),
- disableHiddenApiChecks, mountExtStorageFull, abiOverride);
+ disableHiddenApiChecks, disableTestApiChecks, mountExtStorageFull, abiOverride);
}
return app;
@@ -7923,7 +7922,7 @@
sCallerIdentity.set(new Identity(
token, Binder.getCallingPid(), Binder.getCallingUid()));
try {
- pfd = cph.provider.openFile(null, uri, "r", null, token);
+ pfd = cph.provider.openFile(null, null, uri, "r", null, token);
} catch (FileNotFoundException e) {
// do nothing; pfd will be returned null
} finally {
@@ -10953,7 +10952,7 @@
}
}
pw.print(" mMemWatchDumpProcName="); pw.println(mMemWatchDumpProcName);
- pw.print(" mMemWatchDumpFile="); pw.println(mMemWatchDumpFile);
+ pw.print(" mMemWatchDumpUri="); pw.println(mMemWatchDumpUri);
pw.print(" mMemWatchDumpPid="); pw.println(mMemWatchDumpPid);
pw.print(" mMemWatchDumpUid="); pw.println(mMemWatchDumpUid);
pw.print(" mMemWatchIsUserInitiated="); pw.println(mMemWatchIsUserInitiated);
@@ -11250,10 +11249,14 @@
}
final long dtoken = proto.start(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.DUMP);
- proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PROC_NAME, mMemWatchDumpProcName);
- proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.FILE, mMemWatchDumpFile);
- proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PID, mMemWatchDumpPid);
- proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.UID, mMemWatchDumpUid);
+ proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PROC_NAME,
+ mMemWatchDumpProcName);
+ proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.URI,
+ mMemWatchDumpUri.toString());
+ proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.PID,
+ mMemWatchDumpPid);
+ proto.write(ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.UID,
+ mMemWatchDumpUid);
proto.write(
ActivityManagerServiceDumpProcessesProto.MemWatchProcess.Dump.IS_USER_INITIATED,
mMemWatchIsUserInitiated);
@@ -16061,6 +16064,10 @@
enforceCallingPermission(android.Manifest.permission.DISABLE_HIDDEN_API_CHECKS,
"disable hidden API checks");
}
+ // Allow instrumented processes access to test APIs.
+ // TODO(satayev): make this configurable via testing framework.
+ boolean disableTestApiChecks = true;
+
final boolean mountExtStorageFull = isCallerShell()
&& (flags & INSTR_FLAG_MOUNT_EXTERNAL_STORAGE_FULL) != 0;
@@ -16075,7 +16082,7 @@
}
ProcessRecord app = addAppLocked(ai, defProcess, false, disableHiddenApiChecks,
- mountExtStorageFull, abiOverride);
+ disableTestApiChecks, mountExtStorageFull, abiOverride);
app.setActiveInstrumentation(activeInstr);
activeInstr.mFinished = false;
activeInstr.mRunningProcesses.add(app);
@@ -16366,9 +16373,10 @@
}
}
- void noteUidProcessState(final int uid, final int state) {
+ void noteUidProcessState(final int uid, final int state,
+ final @ActivityManager.ProcessCapability int capability) {
mBatteryStatsService.noteUidProcessState(uid, state);
- mAppOpsService.updateUidProcState(uid, state);
+ mAppOpsService.updateUidProcState(uid, state, capability);
if (mTrackingAssociations) {
for (int i1=0, N1=mAssociations.size(); i1<N1; i1++) {
ArrayMap<ComponentName, SparseArray<ArrayMap<String, Association>>> targetComponents
@@ -16395,56 +16403,44 @@
}
}
- private static final class RecordPssRunnable implements Runnable {
- private final ActivityManagerService mService;
- private final ProcessRecord mProc;
- private final File mHeapdumpFile;
+ /** @hide */
+ public static Uri makeHeapDumpUri(String procName) {
+ return Uri.parse("content://com.android.shell.heapdump/" + procName + "_javaheap.bin");
+ }
- RecordPssRunnable(ActivityManagerService service, ProcessRecord proc, File heapdumpFile) {
- this.mService = service;
- this.mProc = proc;
- this.mHeapdumpFile = heapdumpFile;
+ private final class RecordPssRunnable implements Runnable {
+ private final ProcessRecord mProc;
+ private final Uri mDumpUri;
+ private final ContentResolver mContentResolver;
+
+ RecordPssRunnable(ProcessRecord proc, Uri dumpUri, ContentResolver contentResolver) {
+ mProc = proc;
+ mDumpUri = dumpUri;
+ mContentResolver = contentResolver;
}
@Override
public void run() {
- mService.revokeUriPermission(ActivityThread.currentActivityThread()
- .getApplicationThread(),
- null, DumpHeapActivity.JAVA_URI,
- Intent.FLAG_GRANT_READ_URI_PERMISSION
- | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
- UserHandle.myUserId());
- ParcelFileDescriptor fd = null;
- try {
- mHeapdumpFile.delete();
- fd = ParcelFileDescriptor.open(mHeapdumpFile,
- ParcelFileDescriptor.MODE_CREATE
- | ParcelFileDescriptor.MODE_TRUNCATE
- | ParcelFileDescriptor.MODE_WRITE_ONLY
- | ParcelFileDescriptor.MODE_APPEND);
+ try (ParcelFileDescriptor fd = mContentResolver.openFileDescriptor(mDumpUri, "rw")) {
IApplicationThread thread = mProc.thread;
if (thread != null) {
try {
if (DEBUG_PSS) {
Slog.d(TAG_PSS, "Requesting dump heap from "
- + mProc + " to " + mHeapdumpFile);
+ + mProc + " to " + mDumpUri.getPath());
}
thread.dumpHeap(/* managed= */ true,
/* mallocInfo= */ false, /* runGc= */ false,
- mHeapdumpFile.toString(), fd,
+ mDumpUri.getPath(), fd,
/* finishCallback= */ null);
} catch (RemoteException e) {
}
}
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } finally {
- if (fd != null) {
- try {
- fd.close();
- } catch (IOException e) {
- }
- }
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to dump heap", e);
+ // Need to clear the heap dump variables, otherwise no further heap dumps will be
+ // attempted.
+ abortHeapDump(mProc.processName);
}
}
}
@@ -16513,13 +16509,20 @@
}
private void startHeapDumpLocked(ProcessRecord proc, boolean isUserInitiated) {
- final File heapdumpFile = DumpHeapProvider.getJavaFile();
mMemWatchDumpProcName = proc.processName;
- mMemWatchDumpFile = heapdumpFile.toString();
+ mMemWatchDumpUri = makeHeapDumpUri(proc.processName);
mMemWatchDumpPid = proc.pid;
mMemWatchDumpUid = proc.uid;
mMemWatchIsUserInitiated = isUserInitiated;
- BackgroundThread.getHandler().post(new RecordPssRunnable(this, proc, heapdumpFile));
+ Context ctx;
+ try {
+ ctx = mContext.createPackageContextAsUser("android", 0,
+ UserHandle.getUserHandleForUid(mMemWatchDumpUid));
+ } catch (NameNotFoundException e) {
+ throw new RuntimeException("android package not found.");
+ }
+ BackgroundThread.getHandler().post(
+ new RecordPssRunnable(proc, mMemWatchDumpUri, ctx.getContentResolver()));
}
/**
@@ -16891,6 +16894,7 @@
}
pendingChange.change = change;
pendingChange.processState = uidRec != null ? uidRec.setProcState : PROCESS_STATE_NONEXISTENT;
+ pendingChange.capability = uidRec != null ? uidRec.setCapability : 0;
pendingChange.ephemeral = uidRec != null ? uidRec.ephemeral : isEphemeralLocked(uid);
pendingChange.procStateSeq = uidRec != null ? uidRec.curProcStateSeq : 0;
if (uidRec != null) {
@@ -17715,9 +17719,9 @@
+ " does not match last pid " + mMemWatchDumpPid);
return;
}
- if (mMemWatchDumpFile == null || !mMemWatchDumpFile.equals(path)) {
+ if (mMemWatchDumpUri == null || !mMemWatchDumpUri.getPath().equals(path)) {
Slog.w(TAG, "dumpHeapFinished: Calling path " + path
- + " does not match last path " + mMemWatchDumpFile);
+ + " does not match last path " + mMemWatchDumpUri);
return;
}
if (DEBUG_PSS) Slog.d(TAG_PSS, "Dump heap finished for " + path);
@@ -17728,6 +17732,13 @@
}
}
+ /** Clear the currently executing heap dump variables so a new heap dump can be started. */
+ private void abortHeapDump(String procName) {
+ Message msg = mHandler.obtainMessage(ABORT_DUMPHEAP_MSG);
+ msg.obj = procName;
+ mHandler.sendMessage(msg);
+ }
+
/** In this method we try to acquire our lock to make sure that we have not deadlocked */
public void monitor() {
synchronized (this) { }
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 8be2438..59acdcf 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -1470,7 +1470,8 @@
}
@Override
- public void onUidStateChanged(int uid, int procState, long procStateSeq) throws RemoteException {
+ public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability)
+ throws RemoteException {
synchronized (this) {
final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
try {
@@ -1478,7 +1479,9 @@
mPw.print(" procstate ");
mPw.print(ProcessList.makeProcStateString(procState));
mPw.print(" seq ");
- mPw.println(procStateSeq);
+ mPw.print(procStateSeq);
+ mPw.print(" capability ");
+ mPw.println(capability);
mPw.flush();
} finally {
StrictMode.setThreadPolicy(oldPolicy);
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 6a29c75..8095020 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -383,7 +383,11 @@
// and then the delayed summary kill will be a no-op.
final ProcessRecord p = proc;
mService.mHandler.postDelayed(
- () -> killAppImmediateLocked(p, "forced", "killed for invalid state"),
+ () -> {
+ synchronized (mService) {
+ killAppImmediateLocked(p, "forced", "killed for invalid state");
+ }
+ },
5000L);
}
}
diff --git a/services/core/java/com/android/server/am/DumpHeapProvider.java b/services/core/java/com/android/server/am/DumpHeapProvider.java
deleted file mode 100644
index a8b639e..0000000
--- a/services/core/java/com/android/server/am/DumpHeapProvider.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.am;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Environment;
-import android.os.ParcelFileDescriptor;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-
-public class DumpHeapProvider extends ContentProvider {
- static final Object sLock = new Object();
- static File sHeapDumpJavaFile;
-
- static public File getJavaFile() {
- synchronized (sLock) {
- return sHeapDumpJavaFile;
- }
- }
-
- @Override
- public boolean onCreate() {
- synchronized (sLock) {
- File dataDir = Environment.getDataDirectory();
- File systemDir = new File(dataDir, "system");
- File heapdumpDir = new File(systemDir, "heapdump");
- heapdumpDir.mkdir();
- sHeapDumpJavaFile = new File(heapdumpDir, "javaheap.bin");
- }
- return true;
- }
-
- @Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
- return null;
- }
-
- @Override
- public String getType(Uri uri) {
- return "application/octet-stream";
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- return null;
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- return 0;
- }
-
- @Override
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- return 0;
- }
-
- @Override
- public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
- synchronized (sLock) {
- String path = uri.getEncodedPath();
- final String tag = Uri.decode(path);
- if (tag.equals("/java")) {
- return ParcelFileDescriptor.open(sHeapDumpJavaFile,
- ParcelFileDescriptor.MODE_READ_ONLY);
- } else {
- throw new FileNotFoundException("Invalid path for " + uri);
- }
- }
- }
-}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 78a9efc..30674db 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -16,6 +16,9 @@
package com.android.server.am;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
@@ -23,7 +26,6 @@
import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
-import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
import static android.app.ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
@@ -65,6 +67,7 @@
import android.app.usage.UsageEvents;
import android.content.Context;
import android.content.pm.ServiceInfo;
+import android.os.Build;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
@@ -407,6 +410,13 @@
mAdjSeq--;
// Update these reachable processes
updateOomAdjLockedInner(oomAdjReason, topApp, processes, uids, false);
+ } else if (app.getCurRawAdj() == ProcessList.UNKNOWN_ADJ) {
+ // In case the app goes from non-cached to cached but it doesn't have other reachable
+ // processes, its adj could be still unknown as of now, assign one.
+ processes.add(app);
+ assignCachedAdjIfNecessary(processes);
+ applyOomAdjLocked(app, false, SystemClock.uptimeMillis(),
+ SystemClock.elapsedRealtime());
}
mService.mOomAdjProfiler.oomAdjEnded();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
@@ -471,6 +481,7 @@
app.containsCycle = false;
app.setCurRawProcState(PROCESS_STATE_CACHED_EMPTY);
app.setCurRawAdj(ProcessList.UNKNOWN_ADJ);
+ app.setCapability = PROCESS_CAPABILITY_NONE;
app.resetCachedInfo();
}
for (int i = numProc - 1; i >= 0; i--) {
@@ -486,7 +497,7 @@
}
}
- assignCachedAdjIfNecessary();
+ assignCachedAdjIfNecessary(mProcessList.mLruProcesses);
if (fullUpdate) { // There won't be cycles if we didn't compute clients above.
// Cycle strategy:
@@ -560,8 +571,7 @@
}
}
- private void assignCachedAdjIfNecessary() {
- ArrayList<ProcessRecord> lruList = mProcessList.mLruProcesses;
+ private void assignCachedAdjIfNecessary(ArrayList<ProcessRecord> lruList) {
final int numLru = lruList.size();
// First update the OOM adjustment for each of the
@@ -788,6 +798,7 @@
if (app.hasForegroundServices()) {
uidRec.foregroundServices = true;
}
+ uidRec.curCapability |= app.curCapability;
}
}
@@ -804,10 +815,13 @@
int uidChange = UidRecord.CHANGE_PROCSTATE;
if (uidRec.getCurProcState() != PROCESS_STATE_NONEXISTENT
&& (uidRec.setProcState != uidRec.getCurProcState()
+ || uidRec.setCapability != uidRec.curCapability
|| uidRec.setWhitelist != uidRec.curWhitelist)) {
if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, "Changes in " + uidRec
+ ": proc state from " + uidRec.setProcState + " to "
- + uidRec.getCurProcState() + ", whitelist from " + uidRec.setWhitelist
+ + uidRec.getCurProcState() + ", capability from "
+ + uidRec.setCapability + " to " + uidRec.curCapability
+ + ", whitelist from " + uidRec.setWhitelist
+ " to " + uidRec.curWhitelist);
if (ActivityManager.isProcStateBackground(uidRec.getCurProcState())
&& !uidRec.curWhitelist) {
@@ -845,11 +859,13 @@
uidChange |= isCached ? UidRecord.CHANGE_CACHED : UidRecord.CHANGE_UNCACHED;
}
uidRec.setProcState = uidRec.getCurProcState();
+ uidRec.setCapability = uidRec.curCapability;
uidRec.setWhitelist = uidRec.curWhitelist;
uidRec.setIdle = uidRec.idle;
mService.mAtmInternal.onUidProcStateChanged(uidRec.uid, uidRec.setProcState);
mService.enqueueUidChangeLocked(uidRec, -1, uidChange);
- mService.noteUidProcessState(uidRec.uid, uidRec.getCurProcState());
+ mService.noteUidProcessState(uidRec.uid, uidRec.getCurProcState(),
+ uidRec.curCapability);
if (uidRec.foregroundServices) {
mService.mServices.foregroundServiceProcStateChangedLocked(uidRec);
}
@@ -1016,6 +1032,7 @@
app.curAdj = ProcessList.CACHED_APP_MAX_ADJ;
app.setCurRawAdj(ProcessList.CACHED_APP_MAX_ADJ);
app.completedAdjSeq = app.adjSeq;
+ app.curCapability = PROCESS_CAPABILITY_NONE;
return false;
}
@@ -1030,6 +1047,7 @@
int prevAppAdj = app.curAdj;
int prevProcState = app.getCurProcState();
+ int prevCapability = app.curCapability;
if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
// The max adjustment doesn't allow this app to be anything
@@ -1087,6 +1105,7 @@
int schedGroup;
int procState;
int cachedAdjSeq;
+ int capability = 0;
boolean foregroundActivities = false;
if (PROCESS_STATE_CUR_TOP == PROCESS_STATE_TOP && app == topApp) {
@@ -1185,19 +1204,17 @@
}
}
+ if (app.hasLocationForegroundServices()) {
+ capability |= PROCESS_CAPABILITY_FOREGROUND_LOCATION;
+ }
+
if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
- || procState > PROCESS_STATE_FOREGROUND_SERVICE_LOCATION) {
+ || procState > PROCESS_STATE_FOREGROUND_SERVICE) {
if (app.hasForegroundServices()) {
// The user is aware of this app, so make it visible.
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
- if (app.hasLocationForegroundServices()) {
- procState = PROCESS_STATE_FOREGROUND_SERVICE_LOCATION;
- app.adjType = "fg-service-location";
-
- } else {
- procState = PROCESS_STATE_FOREGROUND_SERVICE;
- app.adjType = "fg-service";
- }
+ procState = PROCESS_STATE_FOREGROUND_SERVICE;
+ app.adjType = "fg-service";
app.cached = false;
schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
if (DEBUG_OOM_ADJ_REASON || logUid == appUid) {
@@ -1437,6 +1454,10 @@
continue;
}
+ if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
+ capability |= client.curCapability;
+ }
+
int clientAdj = client.getCurRawAdj();
int clientProcState = client.getCurRawProcState();
@@ -1549,25 +1570,31 @@
// processes). These should not bring the current process
// into the top state, since they are not on top. Instead
// give them the best bound state after that.
- final int bestState = cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)
- ? PROCESS_STATE_FOREGROUND_SERVICE_LOCATION
- : PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
- if ((cr.flags & Context.BIND_FOREGROUND_SERVICE) != 0) {
- clientProcState = bestState;
+ if (cr.hasFlag(Context.BIND_FOREGROUND_SERVICE)) {
+ clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE; ;
} else if (mService.mWakefulness
== PowerManagerInternal.WAKEFULNESS_AWAKE
&& (cr.flags & Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)
!= 0) {
- clientProcState = bestState;
+ clientProcState = PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
} else {
clientProcState =
PROCESS_STATE_IMPORTANT_FOREGROUND;
}
} else if (clientProcState == PROCESS_STATE_TOP) {
- if (cr.notHasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
- // Go at most to BOUND_TOP, unless requested to elevate
- // to client's state.
- clientProcState = PROCESS_STATE_BOUND_TOP;
+ // Go at most to BOUND_TOP, unless requested to elevate
+ // to client's state.
+ clientProcState = PROCESS_STATE_BOUND_TOP;
+ if (client.info.targetSdkVersion >= Build.VERSION_CODES.R) {
+ if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
+ // TOP process passes all capabilities to the service.
+ capability = PROCESS_CAPABILITY_ALL;
+ } else {
+ // TOP process passes no capability to the service.
+ }
+ } else {
+ // TOP process passes all capabilities to the service.
+ capability = PROCESS_CAPABILITY_ALL;
}
} else if (clientProcState
<= PROCESS_STATE_FOREGROUND_SERVICE) {
@@ -1852,12 +1879,18 @@
}
}
+ // TOP process has all capabilities.
+ if (procState <= PROCESS_STATE_TOP) {
+ capability = PROCESS_CAPABILITY_ALL;
+ }
+
// Do final modification to adj. Everything we do between here and applying
// the final setAdj must be done in this function, because we will also use
// it when computing the final cached adj later. Note that we don't need to
// worry about this for max adj above, since max adj will always be used to
// keep it out of the cached vaues.
app.curAdj = app.modifyRawOomAdj(adj);
+ app.curCapability = capability;
app.setCurrentSchedulingGroup(schedGroup);
app.setCurProcState(procState);
app.setCurRawProcState(procState);
@@ -1865,7 +1898,8 @@
app.completedAdjSeq = mAdjSeq;
// if curAdj or curProcState improved, then this process was promoted
- return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState;
+ return app.curAdj < prevAppAdj || app.getCurProcState() < prevProcState
+ || app.curCapability != prevCapability ;
}
/**
@@ -2175,6 +2209,11 @@
maybeUpdateUsageStatsLocked(app, nowElapsed);
}
+ if (app.curCapability != app.setCapability) {
+ changes |= ActivityManagerService.ProcessChangeItem.CHANGE_CAPABILITY;
+ app.setCapability = app.curCapability;
+ }
+
if (changes != 0) {
if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
"Changes in " + app + ": " + changes);
@@ -2182,12 +2221,13 @@
mService.enqueueProcessChangeItemLocked(app.pid, app.info.uid);
item.changes = changes;
item.foregroundActivities = app.repForegroundActivities;
+ item.capability = app.setCapability;
if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS,
"Item " + Integer.toHexString(System.identityHashCode(item))
+ " " + app.toShortString() + ": changes=" + item.changes
+ " foreground=" + item.foregroundActivities
+ " type=" + app.adjType + " source=" + app.adjSource
- + " target=" + app.adjTarget);
+ + " target=" + app.adjTarget + " capability=" + item.capability);
}
return success;
diff --git a/services/core/java/com/android/server/am/PendingIntentController.java b/services/core/java/com/android/server/am/PendingIntentController.java
index d75591c..df76713 100644
--- a/services/core/java/com/android/server/am/PendingIntentController.java
+++ b/services/core/java/com/android/server/am/PendingIntentController.java
@@ -43,6 +43,7 @@
import com.android.internal.os.IResultReceiver;
import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.AlarmManagerInternal;
import com.android.server.LocalServices;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.SafeActivityOptions;
@@ -293,6 +294,8 @@
PendingIntentController::handlePendingIntentCancelled, this, callbacks);
mH.sendMessage(m);
}
+ final AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class);
+ ami.remove(new PendingIntent(rec));
}
private void handlePendingIntentCancelled(RemoteCallbackList<IResultReceiver> callbacks) {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 8163a6d..2bb7035 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -810,9 +810,6 @@
case ActivityManager.PROCESS_STATE_TOP:
procState = "TOP ";
break;
- case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION:
- procState = "FGSL";
- break;
case ActivityManager.PROCESS_STATE_BOUND_TOP:
procState = "BTOP";
break;
@@ -882,8 +879,6 @@
return AppProtoEnums.PROCESS_STATE_PERSISTENT_UI;
case ActivityManager.PROCESS_STATE_TOP:
return AppProtoEnums.PROCESS_STATE_TOP;
- case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION:
- return AppProtoEnums.PROCESS_STATE_FOREGROUND_SERVICE;
case ActivityManager.PROCESS_STATE_BOUND_TOP:
return AppProtoEnums.PROCESS_STATE_BOUND_TOP;
case ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE:
@@ -1014,7 +1009,6 @@
PROC_MEM_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
PROC_MEM_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
PROC_MEM_TOP, // ActivityManager.PROCESS_STATE_TOP
- PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION
PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
PROC_MEM_TOP, // ActivityManager.PROCESS_STATE_BOUND_TOP
PROC_MEM_IMPORTANT, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
@@ -1329,7 +1323,7 @@
final int procCount = procs.size();
for (int i = 0; i < procCount; i++) {
final int procUid = procs.keyAt(i);
- if (UserHandle.isApp(procUid) || !UserHandle.isSameUser(procUid, uid)) {
+ if (!UserHandle.isCore(procUid) || !UserHandle.isSameUser(procUid, uid)) {
// Don't use an app process or different user process for system component.
continue;
}
@@ -1419,15 +1413,11 @@
/**
* @return {@code true} if process start is successful, false otherwise.
- * @param app
- * @param hostingRecord
- * @param disableHiddenApiChecks
- * @param abiOverride
*/
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
- boolean disableHiddenApiChecks, boolean mountExtStorageFull,
- String abiOverride) {
+ boolean disableHiddenApiChecks, boolean disableTestApiChecks,
+ boolean mountExtStorageFull, String abiOverride) {
if (app.pendingStart) {
return true;
}
@@ -1572,6 +1562,10 @@
throw new IllegalStateException("Invalid API policy: " + policy);
}
runtimeFlags |= policyBits;
+
+ if (disableTestApiChecks) {
+ runtimeFlags |= Zygote.DISABLE_TEST_API_ENFORCEMENT_POLICY;
+ }
}
String useAppImageCache = SystemProperties.get(
@@ -1853,7 +1847,8 @@
final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
String abiOverride) {
return startProcessLocked(app, hostingRecord,
- false /* disableHiddenApiChecks */, false /* mountExtStorageFull */, abiOverride);
+ false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
+ false /* mountExtStorageFull */, abiOverride);
}
@GuardedBy("mService")
@@ -2303,7 +2298,8 @@
uidRec.updateHasInternetPermission();
mActiveUids.put(proc.uid, uidRec);
EventLogTags.writeAmUidRunning(uidRec.uid);
- mService.noteUidProcessState(uidRec.uid, uidRec.getCurProcState());
+ mService.noteUidProcessState(uidRec.uid, uidRec.getCurProcState(),
+ uidRec.curCapability);
}
proc.uidRecord = uidRec;
@@ -2405,7 +2401,8 @@
mService.enqueueUidChangeLocked(old.uidRecord, -1, UidRecord.CHANGE_GONE);
EventLogTags.writeAmUidStopped(uid);
mActiveUids.remove(uid);
- mService.noteUidProcessState(uid, ActivityManager.PROCESS_STATE_NONEXISTENT);
+ mService.noteUidProcessState(uid, ActivityManager.PROCESS_STATE_NONEXISTENT,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
}
old.uidRecord = null;
}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index bf43f3b..1e0693f 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -151,6 +151,9 @@
int curAdj; // Current OOM adjustment for this process
int setAdj; // Last set OOM adjustment for this process
int verifiedAdj; // The last adjustment that was verified as actually being set
+ int curCapability; // Current capability flags of this process. For example,
+ // PROCESS_CAPABILITY_FOREGROUND_LOCATION is one capability.
+ int setCapability; // Last set capability flags.
long lastCompactTime; // The last time that this process was compacted
int reqCompactAction; // The most recent compaction action requested for this app.
int lastCompactAction; // The most recent compaction action performed for this app.
@@ -425,6 +428,8 @@
pw.print(" mRepProcState="); pw.print(mRepProcState);
pw.print(" pssProcState="); pw.print(pssProcState);
pw.print(" setProcState="); pw.print(setProcState);
+ pw.print(" curCapability="); pw.print(curCapability);
+ pw.print(" setCapability="); pw.print(setCapability);
pw.print(" lastStateTime=");
TimeUtils.formatDuration(lastStateTime, nowUptime, pw);
pw.println();
@@ -1097,6 +1102,10 @@
&& (mFgServiceTypes & ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION) != 0;
}
+ boolean hasLocationCapability() {
+ return (setCapability & ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0;
+ }
+
int getForegroundServiceTypes() {
return mHasForegroundServices ? mFgServiceTypes : 0;
}
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index 22a7de7..e6cf287 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -34,6 +34,8 @@
final int uid;
private int mCurProcState;
int setProcState = ActivityManager.PROCESS_STATE_NONEXISTENT;
+ int curCapability;
+ int setCapability;
long lastBackgroundTime;
boolean ephemeral;
boolean foregroundServices;
@@ -108,6 +110,7 @@
int uid;
int change;
int processState;
+ int capability;
boolean ephemeral;
long procStateSeq;
}
@@ -132,6 +135,8 @@
public void reset() {
setCurProcState(ActivityManager.PROCESS_STATE_CACHED_EMPTY);
foregroundServices = false;
+ curCapability = 0;
+
}
public void updateHasInternetPermission() {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 8575068..7e9a17b 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -16,6 +16,7 @@
package com.android.server.appop;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.AppOpsManager.MAX_PRIORITY_UID_STATE;
import static android.app.AppOpsManager.MIN_PRIORITY_UID_STATE;
import static android.app.AppOpsManager.OP_CAMERA;
@@ -27,7 +28,6 @@
import static android.app.AppOpsManager.UID_STATE_CACHED;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
-import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE_LOCATION;
import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED;
import static android.app.AppOpsManager.UID_STATE_PERSISTENT;
import static android.app.AppOpsManager.UID_STATE_TOP;
@@ -47,8 +47,8 @@
import android.app.AppOpsManager.HistoricalOps;
import android.app.AppOpsManager.HistoricalOpsRequest;
import android.app.AppOpsManager.Mode;
-import android.app.AppOpsManager.OpFeatureEntry;
import android.app.AppOpsManager.OpEntry;
+import android.app.AppOpsManager.OpFeatureEntry;
import android.app.AppOpsManager.OpFlags;
import android.app.AppOpsManagerInternal;
import android.app.AppOpsManagerInternal.CheckOpsDelegate;
@@ -164,12 +164,10 @@
UID_STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT
UID_STATE_PERSISTENT, // ActivityManager.PROCESS_STATE_PERSISTENT_UI
UID_STATE_TOP, // ActivityManager.PROCESS_STATE_TOP
- UID_STATE_FOREGROUND_SERVICE_LOCATION,
- // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION
UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_TOP
UID_STATE_FOREGROUND_SERVICE, // ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE
UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE
- UID_STATE_FOREGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
+ UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND
UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND
UID_STATE_BACKGROUND, // ActivityManager.PROCESS_STATE_BACKUP
@@ -364,7 +362,8 @@
public int state = UID_STATE_CACHED;
public int pendingState = UID_STATE_CACHED;
public long pendingStateCommitTime;
-
+ public int capability;
+ public int pendingCapability;
// For all features combined
public int startNesting;
@@ -393,8 +392,25 @@
int evalMode(int op, int mode) {
if (mode == AppOpsManager.MODE_FOREGROUND) {
- return state <= AppOpsManager.resolveFirstUnrestrictedUidState(op)
- ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED;
+ if (state <= UID_STATE_TOP) {
+ // process is in foreground.
+ return AppOpsManager.MODE_ALLOWED;
+ } else if (state <= AppOpsManager.resolveFirstUnrestrictedUidState(op)) {
+ // process is in foreground, check its capability.
+ switch (op) {
+ case AppOpsManager.OP_FINE_LOCATION:
+ case AppOpsManager.OP_COARSE_LOCATION:
+ case AppOpsManager.OP_MONITOR_LOCATION:
+ case AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION:
+ return ((capability & PROCESS_CAPABILITY_FOREGROUND_LOCATION) != 0)
+ ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_IGNORED;
+ default:
+ return AppOpsManager.MODE_ALLOWED;
+ }
+ } else {
+ // process is not in foreground.
+ return AppOpsManager.MODE_IGNORED;
+ }
}
return mode;
}
@@ -1062,13 +1078,16 @@
}
}
- public void updateUidProcState(int uid, int procState) {
+ public void updateUidProcState(int uid, int procState,
+ @ActivityManager.ProcessCapability int capability) {
synchronized (this) {
final UidState uidState = getUidStateLocked(uid, true);
- int newState = PROCESS_STATE_TO_UID_STATE[procState];
- if (uidState != null && uidState.pendingState != newState) {
+ final int newState = PROCESS_STATE_TO_UID_STATE[procState];
+ if (uidState != null && (uidState.pendingState != newState
+ || uidState.pendingCapability != capability)) {
final int oldPendingState = uidState.pendingState;
uidState.pendingState = newState;
+ uidState.pendingCapability = capability;
if (newState < uidState.state
|| (newState <= UID_STATE_MAX_LAST_NON_RESTRICTED
&& uidState.state > UID_STATE_MAX_LAST_NON_RESTRICTED)) {
@@ -1076,6 +1095,9 @@
// foreground and the old state is in the background, then always do it
// immediately.
commitUidPendingStateLocked(uidState);
+ } else if (newState == uidState.state && capability != uidState.capability) {
+ // No change on process state, but process capability has changed.
+ commitUidPendingStateLocked(uidState);
} else if (uidState.pendingStateCommitTime == 0) {
// We are moving to a less important state for the first time,
// delay the application for a bit.
@@ -1182,8 +1204,8 @@
}
} else {
for (int j=0; j<ops.length; j++) {
- int code = uidState.opModes.keyAt(j);
- if (code >= 0) {
+ int code = ops[j];
+ if (uidState.opModes.indexOfKey(code) >= 0) {
if (resOps == null) {
resOps = new ArrayList<>();
}
@@ -2334,7 +2356,6 @@
public void noteAsyncOp(String callingPackageName, int uid, String packageName, int opCode,
String featureId, String message) {
Preconditions.checkNotNull(message);
- Preconditions.checkNotNull(packageName);
verifyAndGetIsPrivileged(uid, packageName);
verifyIncomingUid(uid);
@@ -2857,6 +2878,7 @@
}
}
uidState.state = uidState.pendingState;
+ uidState.capability = uidState.pendingCapability;
uidState.pendingStateCommitTime = 0;
}
@@ -4494,6 +4516,12 @@
pw.print(" pendingState=");
pw.println(AppOpsManager.getUidStateName(uidState.pendingState));
}
+ pw.print(" capability=");
+ pw.println(uidState.capability);
+ if (uidState.capability != uidState.pendingCapability) {
+ pw.print(" pendingCapability=");
+ pw.println(uidState.pendingCapability);
+ }
if (uidState.pendingStateCommitTime != 0) {
pw.print(" pendingStateCommitTime=");
TimeUtils.formatDuration(uidState.pendingStateCommitTime, nowElapsed, pw);
diff --git a/services/core/java/com/android/server/appop/TEST_MAPPING b/services/core/java/com/android/server/appop/TEST_MAPPING
index e9d2b31..9c03a36 100644
--- a/services/core/java/com/android/server/appop/TEST_MAPPING
+++ b/services/core/java/com/android/server/appop/TEST_MAPPING
@@ -35,6 +35,9 @@
"include-filter": "android.permission.cts.SharedUidPermissionsTest"
}
]
+ },
+ {
+ "name": "CtsAppTestCases:ActivityManagerApi29Test"
}
]
}
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 67d3589..232bc08e 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -21,6 +21,7 @@
import static android.service.attention.AttentionService.ATTENTION_FAILURE_UNKNOWN;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.attention.AttentionManagerInternal;
@@ -85,6 +86,10 @@
/** If the check attention called within that period - cached value will be returned. */
private static final long STALE_AFTER_MILLIS = 5_000;
+ /** The size of the buffer that stores recent attention check results. */
+ @VisibleForTesting
+ protected static final int ATTENTION_CACHE_BUFFER_SIZE = 5;
+
/** DeviceConfig flag name, if {@code true}, enables AttentionManagerService features. */
private static final String SERVICE_ENABLED = "service_enabled";
private static String sTestAttentionServicePackage;
@@ -192,7 +197,8 @@
userState.bindLocked();
// throttle frequent requests
- final AttentionCheckCache cache = userState.mAttentionCheckCache;
+ final AttentionCheckCache cache = userState.mAttentionCheckCacheBuffer == null ? null
+ : userState.mAttentionCheckCacheBuffer.getLast();
if (cache != null && now < cache.mLastComputed + STALE_AFTER_MILLIS) {
callbackInternal.onSuccess(cache.mResult, cache.mTimestamp);
return true;
@@ -236,9 +242,11 @@
}
synchronized (mLock) {
- userState.mAttentionCheckCache = new AttentionCheckCache(
- SystemClock.uptimeMillis(), result,
- timestamp);
+ if (userState.mAttentionCheckCacheBuffer == null) {
+ userState.mAttentionCheckCacheBuffer = new AttentionCheckCacheBuffer();
+ }
+ userState.mAttentionCheckCacheBuffer.add(
+ new AttentionCheckCache(SystemClock.uptimeMillis(), result, timestamp));
}
StatsLog.write(
StatsLog.ATTENTION_MANAGER_SERVICE_RESULT_REPORTED,
@@ -421,7 +429,41 @@
}
}
- private static final class AttentionCheckCache {
+ @VisibleForTesting
+ protected static final class AttentionCheckCacheBuffer {
+ private final AttentionCheckCache[] mQueue;
+ private int mStartIndex;
+ private int mSize;
+
+ AttentionCheckCacheBuffer() {
+ mQueue = new AttentionCheckCache[ATTENTION_CACHE_BUFFER_SIZE];
+ mStartIndex = 0;
+ mSize = 0;
+ }
+
+ public AttentionCheckCache getLast() {
+ int lastIdx = (mStartIndex + mSize - 1) % ATTENTION_CACHE_BUFFER_SIZE;
+ return mSize == 0 ? null : mQueue[lastIdx];
+ }
+
+ public void add(@NonNull AttentionCheckCache cache) {
+ int nextIndex = (mStartIndex + mSize) % ATTENTION_CACHE_BUFFER_SIZE;
+ mQueue[nextIndex] = cache;
+ if (mSize == ATTENTION_CACHE_BUFFER_SIZE) {
+ mStartIndex++;
+ } else {
+ mSize++;
+ }
+ }
+
+ public AttentionCheckCache get(int offset) {
+ return offset >= mSize ? null
+ : mQueue[(mStartIndex + offset) % ATTENTION_CACHE_BUFFER_SIZE];
+ }
+ }
+
+ @VisibleForTesting
+ protected static final class AttentionCheckCache {
private final long mLastComputed;
private final int mResult;
private final long mTimestamp;
@@ -463,7 +505,7 @@
@GuardedBy("mLock")
AttentionCheck mCurrentAttentionCheck;
@GuardedBy("mLock")
- AttentionCheckCache mAttentionCheckCache;
+ AttentionCheckCacheBuffer mAttentionCheckCacheBuffer;
@GuardedBy("mLock")
private boolean mBinding;
@@ -532,13 +574,14 @@
pw.println("is fulfilled:=" + mCurrentAttentionCheck.mIsFulfilled);
pw.decreaseIndent();
}
- pw.println("attention check cache:");
- if (mAttentionCheckCache != null) {
- pw.increaseIndent();
- pw.println("last computed=" + mAttentionCheckCache.mLastComputed);
- pw.println("timestamp=" + mAttentionCheckCache.mTimestamp);
- pw.println("result=" + mAttentionCheckCache.mResult);
- pw.decreaseIndent();
+ if (mAttentionCheckCacheBuffer != null) {
+ pw.println("attention check cache:");
+ for (int i = 0; i < mAttentionCheckCacheBuffer.mSize; i++) {
+ pw.increaseIndent();
+ pw.println("timestamp=" + mAttentionCheckCacheBuffer.get(i).mTimestamp);
+ pw.println("result=" + mAttentionCheckCacheBuffer.get(i).mResult);
+ pw.decreaseIndent();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 0d493b8..6355af6 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -580,7 +580,8 @@
}
final private IUidObserver mUidObserver = new IUidObserver.Stub() {
- @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
+ @Override public void onUidStateChanged(int uid, int procState, long procStateSeq,
+ int capability) {
}
@Override public void onUidGone(int uid, boolean disabled) {
@@ -1582,12 +1583,13 @@
setMicrophoneMuteNoCallerCheck(currentUser);
}
- private int rescaleIndex(int index, int srcStream, int dstStream) {
- int srcRange =
- mStreamStates[srcStream].getMaxIndex() - mStreamStates[srcStream].getMinIndex();
- int dstRange =
- mStreamStates[dstStream].getMaxIndex() - mStreamStates[dstStream].getMinIndex();
+ private int getIndexRange(int streamType) {
+ return (mStreamStates[streamType].getMaxIndex() - mStreamStates[streamType].getMinIndex());
+ }
+ private int rescaleIndex(int index, int srcStream, int dstStream) {
+ int srcRange = getIndexRange(srcStream);
+ int dstRange = getIndexRange(dstStream);
if (srcRange == 0) {
Log.e(TAG, "rescaleIndex : index range should not be zero");
return mStreamStates[dstStream].getMinIndex();
@@ -1598,6 +1600,17 @@
/ srcRange;
}
+ private int rescaleStep(int step, int srcStream, int dstStream) {
+ int srcRange = getIndexRange(srcStream);
+ int dstRange = getIndexRange(dstStream);
+ if (srcRange == 0) {
+ Log.e(TAG, "rescaleStep : index range should not be zero");
+ return 0;
+ }
+
+ return ((step * dstRange + srcRange / 2) / srcRange);
+ }
+
///////////////////////////////////////////////////////////////////////////
// IPC methods
///////////////////////////////////////////////////////////////////////////
@@ -1774,7 +1787,7 @@
}
} else {
// convert one UI step (+/-1) into a number of internal units on the stream alias
- step = rescaleIndex(10, streamType, streamTypeAlias);
+ step = rescaleStep(10, streamType, streamTypeAlias);
}
// If either the client forces allowing ringer modes for this adjustment,
@@ -2784,6 +2797,7 @@
}
public void setMasterMute(boolean mute, int flags, String callingPackage, int userId) {
+ enforceModifyAudioRoutingPermission();
setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid(),
userId);
}
diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java
index bc5973d..8762435 100644
--- a/services/core/java/com/android/server/compat/CompatChange.java
+++ b/services/core/java/com/android/server/compat/CompatChange.java
@@ -20,6 +20,7 @@
import android.compat.annotation.EnabledAfter;
import android.content.pm.ApplicationInfo;
+import com.android.internal.compat.CompatibilityChangeInfo;
import com.android.server.compat.config.Change;
import java.util.HashMap;
@@ -35,12 +36,8 @@
*
* <p>Note, this class is not thread safe so callers must ensure thread safety.
*/
-public final class CompatChange {
+public final class CompatChange extends CompatibilityChangeInfo {
- private final long mChangeId;
- @Nullable private final String mName;
- private final int mEnableAfterTargetSdk;
- private final boolean mDisabled;
private Map<String, Boolean> mPackageOverrides;
public CompatChange(long changeId) {
@@ -56,29 +53,15 @@
*/
public CompatChange(long changeId, @Nullable String name, int enableAfterTargetSdk,
boolean disabled) {
- mChangeId = changeId;
- mName = name;
- mEnableAfterTargetSdk = enableAfterTargetSdk;
- mDisabled = disabled;
+ super(changeId, name, enableAfterTargetSdk, disabled);
}
/**
* @param change an object generated by services/core/xsd/platform-compat-config.xsd
*/
public CompatChange(Change change) {
- mChangeId = change.getId();
- mName = change.getName();
- mEnableAfterTargetSdk = change.getEnableAfterTargetSdk();
- mDisabled = change.getDisabled();
- }
-
- long getId() {
- return mChangeId;
- }
-
- @Nullable
- String getName() {
- return mName;
+ super(change.getId(), change.getName(), change.getEnableAfterTargetSdk(),
+ change.getDisabled());
}
/**
@@ -121,11 +104,11 @@
if (mPackageOverrides != null && mPackageOverrides.containsKey(app.packageName)) {
return mPackageOverrides.get(app.packageName);
}
- if (mDisabled) {
+ if (getDisabled()) {
return false;
}
- if (mEnableAfterTargetSdk != -1) {
- return app.targetSdkVersion > mEnableAfterTargetSdk;
+ if (getEnableAfterTargetSdk() != -1) {
+ return app.targetSdkVersion > getEnableAfterTargetSdk();
}
return true;
}
@@ -133,14 +116,14 @@
@Override
public String toString() {
StringBuilder sb = new StringBuilder("ChangeId(")
- .append(mChangeId);
- if (mName != null) {
- sb.append("; name=").append(mName);
+ .append(getId());
+ if (getName() != null) {
+ sb.append("; name=").append(getName());
}
- if (mEnableAfterTargetSdk != -1) {
- sb.append("; enableAfterTargetSdk=").append(mEnableAfterTargetSdk);
+ if (getEnableAfterTargetSdk() != -1) {
+ sb.append("; enableAfterTargetSdk=").append(getEnableAfterTargetSdk());
}
- if (mDisabled) {
+ if (getDisabled()) {
sb.append("; disabled");
}
if (mPackageOverrides != null && mPackageOverrides.size() > 0) {
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index 0fabd9a..d6ec22b 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -16,6 +16,7 @@
package com.android.server.compat;
+import android.compat.Compatibility.ChangeConfig;
import android.content.pm.ApplicationInfo;
import android.os.Environment;
import android.text.TextUtils;
@@ -26,6 +27,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.compat.CompatibilityChangeConfig;
+import com.android.internal.compat.CompatibilityChangeInfo;
import com.android.server.compat.config.Change;
import com.android.server.compat.config.XmlParser;
@@ -37,6 +39,8 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Set;
import javax.xml.datatype.DatatypeConfigurationException;
/**
@@ -243,6 +247,49 @@
}
}
+ /**
+ * Get the config for a given app.
+ *
+ * @param applicationInfo the {@link ApplicationInfo} for which the info should be dumped.
+ * @return A {@link CompatibilityChangeConfig} which contains the compat config info for the
+ * given app.
+ */
+
+ public CompatibilityChangeConfig getAppConfig(ApplicationInfo applicationInfo) {
+ Set<Long> enabled = new HashSet<>();
+ Set<Long> disabled = new HashSet<>();
+ synchronized (mChanges) {
+ for (int i = 0; i < mChanges.size(); ++i) {
+ CompatChange c = mChanges.valueAt(i);
+ if (c.isEnabled(applicationInfo)) {
+ enabled.add(c.getId());
+ } else {
+ disabled.add(c.getId());
+ }
+ }
+ }
+ return new CompatibilityChangeConfig(new ChangeConfig(enabled, disabled));
+ }
+
+ /**
+ * Dumps all the compatibility change information.
+ *
+ * @return An array of {@link CompatibilityChangeInfo} with the current changes.
+ */
+ public CompatibilityChangeInfo[] dumpChanges() {
+ synchronized (mChanges) {
+ CompatibilityChangeInfo[] changeInfos = new CompatibilityChangeInfo[mChanges.size()];
+ for (int i = 0; i < mChanges.size(); ++i) {
+ CompatChange change = mChanges.valueAt(i);
+ changeInfos[i] = new CompatibilityChangeInfo(change.getId(),
+ change.getName(),
+ change.getEnableAfterTargetSdk(),
+ change.getDisabled());
+ }
+ return changeInfos;
+ }
+ }
+
CompatConfig initConfigFromLib(File libraryDir) {
if (!libraryDir.exists() || !libraryDir.isDirectory()) {
Slog.e(TAG, "No directory " + libraryDir + ", skipping");
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 9ac9955..75e2d22 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -25,6 +25,7 @@
import com.android.internal.compat.ChangeReporter;
import com.android.internal.compat.CompatibilityChangeConfig;
+import com.android.internal.compat.CompatibilityChangeInfo;
import com.android.internal.compat.IPlatformCompat;
import com.android.internal.util.DumpUtils;
@@ -114,6 +115,16 @@
}
@Override
+ public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) {
+ return CompatConfig.get().getAppConfig(appInfo);
+ }
+
+ @Override
+ public CompatibilityChangeInfo[] listAllChanges() {
+ return CompatConfig.get().dumpChanges();
+ }
+
+ @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
CompatConfig.get().dumpConfig(pw);
diff --git a/services/core/java/com/android/server/display/color/DisplayTransformManager.java b/services/core/java/com/android/server/display/color/DisplayTransformManager.java
index d5706a5..3b0069c 100644
--- a/services/core/java/com/android/server/display/color/DisplayTransformManager.java
+++ b/services/core/java/com/android/server/display/color/DisplayTransformManager.java
@@ -111,6 +111,8 @@
@GuardedBy("mDaltonizerModeLock")
private int mDaltonizerMode = -1;
+ private static final IBinder sFlinger = ServiceManager.getService(SURFACE_FLINGER);
+
/* package */ DisplayTransformManager() {
}
@@ -195,25 +197,22 @@
* Propagates the provided color transformation matrix to the SurfaceFlinger.
*/
private static void applyColorMatrix(float[] m) {
- final IBinder flinger = ServiceManager.getService(SURFACE_FLINGER);
- if (flinger != null) {
- final Parcel data = Parcel.obtain();
- data.writeInterfaceToken("android.ui.ISurfaceComposer");
- if (m != null) {
- data.writeInt(1);
- for (int i = 0; i < 16; i++) {
- data.writeFloat(m[i]);
- }
- } else {
- data.writeInt(0);
+ final Parcel data = Parcel.obtain();
+ data.writeInterfaceToken("android.ui.ISurfaceComposer");
+ if (m != null) {
+ data.writeInt(1);
+ for (int i = 0; i < 16; i++) {
+ data.writeFloat(m[i]);
}
- try {
- flinger.transact(SURFACE_FLINGER_TRANSACTION_COLOR_MATRIX, data, null, 0);
- } catch (RemoteException ex) {
- Slog.e(TAG, "Failed to set color transform", ex);
- } finally {
- data.recycle();
- }
+ } else {
+ data.writeInt(0);
+ }
+ try {
+ sFlinger.transact(SURFACE_FLINGER_TRANSACTION_COLOR_MATRIX, data, null, 0);
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Failed to set color transform", ex);
+ } finally {
+ data.recycle();
}
}
@@ -221,18 +220,15 @@
* Propagates the provided Daltonization mode to the SurfaceFlinger.
*/
private static void applyDaltonizerMode(int mode) {
- final IBinder flinger = ServiceManager.getService(SURFACE_FLINGER);
- if (flinger != null) {
- final Parcel data = Parcel.obtain();
- data.writeInterfaceToken("android.ui.ISurfaceComposer");
- data.writeInt(mode);
- try {
- flinger.transact(SURFACE_FLINGER_TRANSACTION_DALTONIZER, data, null, 0);
- } catch (RemoteException ex) {
- Slog.e(TAG, "Failed to set Daltonizer mode", ex);
- } finally {
- data.recycle();
- }
+ final Parcel data = Parcel.obtain();
+ data.writeInterfaceToken("android.ui.ISurfaceComposer");
+ data.writeInt(mode);
+ try {
+ sFlinger.transact(SURFACE_FLINGER_TRANSACTION_DALTONIZER, data, null, 0);
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Failed to set Daltonizer mode", ex);
+ } finally {
+ data.recycle();
}
}
@@ -286,20 +282,17 @@
* #SURFACE_FLINGER_TRANSACTION_QUERY_COLOR_MANAGED}.
*/
public boolean isDeviceColorManaged() {
- final IBinder flinger = ServiceManager.getService(SURFACE_FLINGER);
- if (flinger != null) {
- final Parcel data = Parcel.obtain();
- final Parcel reply = Parcel.obtain();
- data.writeInterfaceToken("android.ui.ISurfaceComposer");
- try {
- flinger.transact(SURFACE_FLINGER_TRANSACTION_QUERY_COLOR_MANAGED, data, reply, 0);
- return reply.readBoolean();
- } catch (RemoteException ex) {
- Slog.e(TAG, "Failed to query wide color support", ex);
- } finally {
- data.recycle();
- reply.recycle();
- }
+ final Parcel data = Parcel.obtain();
+ final Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken("android.ui.ISurfaceComposer");
+ try {
+ sFlinger.transact(SURFACE_FLINGER_TRANSACTION_QUERY_COLOR_MANAGED, data, reply, 0);
+ return reply.readBoolean();
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Failed to query wide color support", ex);
+ } finally {
+ data.recycle();
+ reply.recycle();
}
return false;
}
@@ -309,18 +302,15 @@
*/
private void applySaturation(float saturation) {
SystemProperties.set(PERSISTENT_PROPERTY_SATURATION, Float.toString(saturation));
- final IBinder flinger = ServiceManager.getService(SURFACE_FLINGER);
- if (flinger != null) {
- final Parcel data = Parcel.obtain();
- data.writeInterfaceToken("android.ui.ISurfaceComposer");
- data.writeFloat(saturation);
- try {
- flinger.transact(SURFACE_FLINGER_TRANSACTION_SATURATION, data, null, 0);
- } catch (RemoteException ex) {
- Slog.e(TAG, "Failed to set saturation", ex);
- } finally {
- data.recycle();
- }
+ final Parcel data = Parcel.obtain();
+ data.writeInterfaceToken("android.ui.ISurfaceComposer");
+ data.writeFloat(saturation);
+ try {
+ sFlinger.transact(SURFACE_FLINGER_TRANSACTION_SATURATION, data, null, 0);
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Failed to set saturation", ex);
+ } finally {
+ data.recycle();
}
}
@@ -334,21 +324,18 @@
Integer.toString(compositionColorMode));
}
- final IBinder flinger = ServiceManager.getService(SURFACE_FLINGER);
- if (flinger != null) {
- final Parcel data = Parcel.obtain();
- data.writeInterfaceToken("android.ui.ISurfaceComposer");
- data.writeInt(color);
- if (compositionColorMode != Display.COLOR_MODE_INVALID) {
- data.writeInt(compositionColorMode);
- }
- try {
- flinger.transact(SURFACE_FLINGER_TRANSACTION_DISPLAY_COLOR, data, null, 0);
- } catch (RemoteException ex) {
- Slog.e(TAG, "Failed to set display color", ex);
- } finally {
- data.recycle();
- }
+ final Parcel data = Parcel.obtain();
+ data.writeInterfaceToken("android.ui.ISurfaceComposer");
+ data.writeInt(color);
+ if (compositionColorMode != Display.COLOR_MODE_INVALID) {
+ data.writeInt(compositionColorMode);
+ }
+ try {
+ sFlinger.transact(SURFACE_FLINGER_TRANSACTION_DISPLAY_COLOR, data, null, 0);
+ } catch (RemoteException ex) {
+ Slog.e(TAG, "Failed to set display color", ex);
+ } finally {
+ data.recycle();
}
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 362955d..67a23dd 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -496,8 +496,6 @@
}
InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
- // Give the output channel a token just for identity purposes.
- inputChannels[0].setToken(new Binder());
nativeRegisterInputMonitor(mPtr, inputChannels[0], displayId, false /*isGestureMonitor*/);
inputChannels[0].dispose(); // don't need to retain the Java object reference
return inputChannels[1];
@@ -528,7 +526,6 @@
try {
InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
InputMonitorHost host = new InputMonitorHost(inputChannels[0]);
- inputChannels[0].setToken(host.asBinder());
nativeRegisterInputMonitor(mPtr, inputChannels[0], displayId,
true /*isGestureMonitor*/);
return new InputMonitor(inputChannels[1], host);
@@ -547,7 +544,6 @@
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null.");
}
- inputChannel.setToken(new Binder());
nativeRegisterInputChannel(mPtr, inputChannel);
}
@@ -1810,8 +1806,9 @@
}
// Native callback.
- private long notifyANR(IBinder token, String reason) {
- return mWindowManagerCallbacks.notifyANR(
+ private long notifyANR(InputApplicationHandle inputApplicationHandle, IBinder token,
+ String reason) {
+ return mWindowManagerCallbacks.notifyANR(inputApplicationHandle,
token, reason);
}
@@ -2055,7 +2052,12 @@
public void notifyInputChannelBroken(IBinder token);
- public long notifyANR(IBinder token, String reason);
+ /**
+ * Notifies the window manager about an application that is not responding.
+ * Returns a new timeout to continue waiting in nanoseconds, or 0 to abort dispatch.
+ */
+ long notifyANR(InputApplicationHandle inputApplicationHandle, IBinder token,
+ String reason);
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
@@ -2182,7 +2184,7 @@
@Override
public void pilferPointers() {
- nativePilferPointers(mPtr, asBinder());
+ nativePilferPointers(mPtr, mInputChannel.getToken());
}
@Override
diff --git a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
new file mode 100644
index 0000000..c1567bc
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.parser;
+
+import com.android.server.integrity.model.Rule;
+
+import java.io.InputStream;
+
+/** A helper class to parse rules into the {@link Rule} model from Binary representation. */
+public class RuleBinaryParser implements RuleParser {
+
+ @Override
+ public Rule parse(String ruleText) {
+ // TODO: Implement binary text parser.
+ return null;
+ }
+
+ @Override
+ public Rule parse(InputStream inputStream) {
+ // TODO: Implement stream parser.
+ return null;
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/parser/RuleParser.java b/services/core/java/com/android/server/integrity/parser/RuleParser.java
new file mode 100644
index 0000000..96ed5993
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/parser/RuleParser.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.parser;
+
+import com.android.server.integrity.model.Rule;
+
+import java.io.InputStream;
+
+/** A helper class to parse rules into the {@link Rule} model. */
+public interface RuleParser {
+
+ /** Parse rules from a string. */
+ Rule parse(String ruleText);
+
+ /** Parse rules from an input stream. */
+ Rule parse(InputStream inputStream);
+}
diff --git a/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
new file mode 100644
index 0000000..8b1bec9
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/parser/RuleXmlParser.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.parser;
+
+import com.android.server.integrity.model.Rule;
+
+import java.io.InputStream;
+
+/** A helper class to parse rules into the {@link Rule} model from Xml representation. */
+public final class RuleXmlParser implements RuleParser {
+
+ @Override
+ public Rule parse(String ruleText) {
+ // TODO: Implement text parser.
+ return null;
+ }
+
+ @Override
+ public Rule parse(InputStream inputStream) {
+ // TODO: Implement stream parser.
+ return null;
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
new file mode 100644
index 0000000..ecb00a4
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.serializer;
+
+import com.android.server.integrity.model.Rule;
+
+import java.io.OutputStream;
+
+/** A helper class to serialize rules from the {@link Rule} model to Xml representation. */
+public class RuleBinarySerializer implements RuleSerializer {
+
+ @Override
+ public void serialize(Rule rule, OutputStream outputStream) {
+ // TODO: Implement stream serializer.
+ }
+
+ @Override
+ public String serialize(Rule rule) {
+ // TODO: Implement text serializer.
+ return null;
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java
new file mode 100644
index 0000000..07a912f
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.serializer;
+
+import com.android.server.integrity.model.Rule;
+
+import java.io.OutputStream;
+
+/** A helper class to serialize rules from the {@link Rule} model. */
+public interface RuleSerializer {
+
+ /** Serialize a rule to an output stream */
+ void serialize(Rule rule, OutputStream outputStream);
+
+ /** Serialize a rule to a string. */
+ String serialize(Rule rule);
+}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
new file mode 100644
index 0000000..62973e2
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.serializer;
+
+import com.android.server.integrity.model.Rule;
+
+import java.io.OutputStream;
+
+/** A helper class to serialize rules from the {@link Rule} model to Xml representation. */
+public class RuleXmlSerializer implements RuleSerializer {
+
+ @Override
+ public void serialize(Rule rule, OutputStream outputStream) {
+ // TODO: Implement stream serializer.
+ }
+
+ @Override
+ public String serialize(Rule rule) {
+ // TODO: Implement text serializer.
+ return null;
+ }
+}
diff --git a/services/core/java/com/android/server/location/GeocoderProxy.java b/services/core/java/com/android/server/location/GeocoderProxy.java
index d9602b8..e6f0ed9 100644
--- a/services/core/java/com/android/server/location/GeocoderProxy.java
+++ b/services/core/java/com/android/server/location/GeocoderProxy.java
@@ -21,7 +21,7 @@
import android.location.GeocoderParams;
import android.location.IGeocodeProvider;
-import com.android.server.FgThread;
+import com.android.internal.os.BackgroundThread;
import com.android.server.ServiceWatcher;
import java.util.List;
@@ -53,7 +53,7 @@
int initialPackageNamesResId) {
mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, overlaySwitchResId,
defaultServicePackageNameResId, initialPackageNamesResId,
- FgThread.getHandler());
+ BackgroundThread.getHandler());
}
private boolean bind() {
diff --git a/services/core/java/com/android/server/location/GeofenceManager.java b/services/core/java/com/android/server/location/GeofenceManager.java
index 17a2169..81c06d7 100644
--- a/services/core/java/com/android/server/location/GeofenceManager.java
+++ b/services/core/java/com/android/server/location/GeofenceManager.java
@@ -18,12 +18,11 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
-import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
-import android.database.ContentObserver;
import android.location.Geofence;
import android.location.Location;
import android.location.LocationListener;
@@ -31,13 +30,14 @@
import android.location.LocationRequest;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.SystemClock;
-import android.os.UserHandle;
-import android.provider.Settings;
+import android.util.Log;
import android.util.Slog;
+import com.android.server.FgThread;
import com.android.server.LocationManagerService;
import com.android.server.PendingIntentUtils;
@@ -48,7 +48,7 @@
public class GeofenceManager implements LocationListener, PendingIntent.OnFinished {
private static final String TAG = "GeofenceManager";
- private static final boolean D = LocationManagerService.D;
+ private static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
private static final int MSG_UPDATE_FENCES = 1;
@@ -64,10 +64,6 @@
*/
private static final long MAX_AGE_NANOS = 5 * 60 * 1000000000L; // five minutes
- /**
- * The default value of most frequent update interval allowed.
- */
- private static final long DEFAULT_MIN_INTERVAL_MS = 30 * 60 * 1000; // 30 minutes
/**
* Least frequent update interval allowed.
@@ -75,11 +71,13 @@
private static final long MAX_INTERVAL_MS = 2 * 60 * 60 * 1000; // two hours
private final Context mContext;
+ private final GeofenceHandler mHandler;
+
private final LocationManager mLocationManager;
private final AppOpsManager mAppOps;
private final PowerManager.WakeLock mWakeLock;
- private final GeofenceHandler mHandler;
- private final LocationBlacklist mBlacklist;
+
+ private final LocationSettingsStore mSettingsStore;
private final Object mLock = new Object();
@@ -113,43 +111,17 @@
*/
private boolean mPendingUpdate;
- /**
- * The actual value of most frequent update interval allowed.
- */
- private long mEffectiveMinIntervalMs;
- private ContentResolver mResolver;
-
- public GeofenceManager(Context context, LocationBlacklist blacklist) {
+ public GeofenceManager(Context context, LocationSettingsStore settingsStore) {
mContext = context;
- mLocationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
- mAppOps = (AppOpsManager)mContext.getSystemService(Context.APP_OPS_SERVICE);
- PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
- mHandler = new GeofenceHandler();
- mBlacklist = blacklist;
- mResolver = mContext.getContentResolver();
- updateMinInterval();
- mResolver.registerContentObserver(
- Settings.Global.getUriFor(
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS),
- true,
- new ContentObserver(mHandler) {
- @Override
- public void onChange(boolean selfChange) {
- synchronized (mLock) {
- updateMinInterval();
- }
- }
- }, UserHandle.USER_ALL);
- }
+ mHandler = new GeofenceHandler(FgThread.getHandler().getLooper());
- /**
- * Updates the minimal location request frequency.
- */
- private void updateMinInterval() {
- mEffectiveMinIntervalMs = Settings.Global.getLong(mResolver,
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
- DEFAULT_MIN_INTERVAL_MS);
+ mLocationManager = mContext.getSystemService(LocationManager.class);
+ mAppOps = mContext.getSystemService(AppOpsManager.class);
+
+ mWakeLock = mContext.getSystemService(PowerManager.class).newWakeLock(
+ PowerManager.PARTIAL_WAKE_LOCK, TAG);
+
+ mSettingsStore = settingsStore;
}
public void addFence(LocationRequest request, Geofence geofence, PendingIntent intent,
@@ -161,8 +133,8 @@
}
GeofenceState state = new GeofenceState(geofence,
- request.getExpireAt(), allowedResolutionLevel, uid, packageName, featureId,
- listenerIdentifier, intent);
+ request.getExpirationRealtimeMs(SystemClock.elapsedRealtime()),
+ allowedResolutionLevel, uid, packageName, featureId, listenerIdentifier, intent);
synchronized (mLock) {
// first make sure it doesn't already exist
for (int i = mFences.size() - 1; i >= 0; i--) {
@@ -294,7 +266,8 @@
double minFenceDistance = Double.MAX_VALUE;
boolean needUpdates = false;
for (GeofenceState state : mFences) {
- if (mBlacklist.isBlacklisted(state.mPackageName)) {
+ if (mSettingsStore.isLocationPackageBlacklisted(ActivityManager.getCurrentUser(),
+ state.mPackageName)) {
if (D) {
Slog.d(TAG, "skipping geofence processing for blacklisted app: "
+ state.mPackageName);
@@ -340,10 +313,11 @@
// Compute a location update interval based on the distance to the nearest fence.
long intervalMs;
if (location != null && Double.compare(minFenceDistance, Double.MAX_VALUE) != 0) {
- intervalMs = (long)Math.min(MAX_INTERVAL_MS, Math.max(mEffectiveMinIntervalMs,
+ intervalMs = (long) Math.min(MAX_INTERVAL_MS, Math.max(
+ mSettingsStore.getBackgroundThrottleProximityAlertIntervalMs(),
minFenceDistance * 1000 / MAX_SPEED_M_S));
} else {
- intervalMs = mEffectiveMinIntervalMs;
+ intervalMs = mSettingsStore.getBackgroundThrottleProximityAlertIntervalMs();
}
if (!mReceivingLocationUpdates || mLocationUpdateInterval != intervalMs) {
mReceivingLocationUpdates = true;
@@ -436,13 +410,16 @@
}
@Override
- public void onStatusChanged(String provider, int status, Bundle extras) { }
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ }
@Override
- public void onProviderEnabled(String provider) { }
+ public void onProviderEnabled(String provider) {
+ }
@Override
- public void onProviderDisabled(String provider) { }
+ public void onProviderDisabled(String provider) {
+ }
@Override
public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
@@ -457,17 +434,14 @@
}
private final class GeofenceHandler extends Handler {
- public GeofenceHandler() {
- super(true /*async*/);
+ private GeofenceHandler(Looper looper) {
+ super(looper);
}
@Override
public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_UPDATE_FENCES: {
- updateFences();
- break;
- }
+ if (msg.what == MSG_UPDATE_FENCES) {
+ updateFences();
}
}
}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 11b9ac4..fb57d69 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -589,9 +589,17 @@
if (sStaticTestOverride) {
return true;
}
+ ensureInitialized();
return native_is_supported();
}
+ private static synchronized void ensureInitialized() {
+ if (!sIsInitialized) {
+ class_init_native();
+ }
+ sIsInitialized = true;
+ }
+
private void reloadGpsProperties() {
mGnssConfiguration.reloadGpsProperties();
setSuplHostPort();
@@ -610,12 +618,7 @@
Looper looper) {
super(context, locationProviderManager);
- synchronized (mLock) {
- if (!sIsInitialized) {
- class_init_native();
- }
- sIsInitialized = true;
- }
+ ensureInitialized();
mLooper = looper;
@@ -833,7 +836,7 @@
int elapsedRealtimeFlags = ELAPSED_REALTIME_HAS_TIMESTAMP_NS
| (location.hasElapsedRealtimeUncertaintyNanos()
- ? ELAPSED_REALTIME_HAS_TIME_UNCERTAINTY_NS : 0);
+ ? ELAPSED_REALTIME_HAS_TIME_UNCERTAINTY_NS : 0);
long elapsedRealtimeNanos = location.getElapsedRealtimeNanos();
double elapsedRealtimeUncertaintyNanos = location.getElapsedRealtimeUncertaintyNanos();
@@ -1024,7 +1027,7 @@
// .. but enable anyway, if there's an active settings-ignored request (e.g. ELS)
enabled |= (mProviderRequest != null && mProviderRequest.reportLocation
- && mProviderRequest.locationSettingsIgnored);
+ && mProviderRequest.locationSettingsIgnored);
// ... and, finally, disable anyway, if device is being shut down
enabled &= !mShutdown;
diff --git a/services/core/java/com/android/server/location/LocationBlacklist.java b/services/core/java/com/android/server/location/LocationBlacklist.java
deleted file mode 100644
index 3f3f828..0000000
--- a/services/core/java/com/android/server/location/LocationBlacklist.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package com.android.server.location;
-
-import android.content.Context;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.Log;
-import android.util.Slog;
-
-import com.android.server.LocationManagerService;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * Allows applications to be blacklisted from location updates at run-time.
- *
- * This is a silent blacklist. Applications can still call Location Manager
- * API's, but they just won't receive any locations.
- */
-public final class LocationBlacklist extends ContentObserver {
- private static final String TAG = "LocationBlacklist";
- private static final boolean D = LocationManagerService.D;
- private static final String BLACKLIST_CONFIG_NAME = "locationPackagePrefixBlacklist";
- private static final String WHITELIST_CONFIG_NAME = "locationPackagePrefixWhitelist";
-
- private final Context mContext;
- private final Object mLock = new Object();
-
- // all fields below synchronized on mLock
- private String[] mWhitelist = new String[0];
- private String[] mBlacklist = new String[0];
-
- private int mCurrentUserId = UserHandle.USER_SYSTEM;
-
- public LocationBlacklist(Context context, Handler handler) {
- super(handler);
- mContext = context;
- }
-
- public void init() {
- mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
- BLACKLIST_CONFIG_NAME), false, this, UserHandle.USER_ALL);
-// mContext.getContentResolver().registerContentObserver(Settings.Secure.getUriFor(
-// WHITELIST_CONFIG_NAME), false, this, UserHandle.USER_ALL);
- reloadBlacklist();
- }
-
- private void reloadBlacklistLocked() {
- mWhitelist = getStringArrayLocked(WHITELIST_CONFIG_NAME);
- if (D) Slog.d(TAG, "whitelist: " + Arrays.toString(mWhitelist));
- mBlacklist = getStringArrayLocked(BLACKLIST_CONFIG_NAME);
- if (D) Slog.d(TAG, "blacklist: " + Arrays.toString(mBlacklist));
- }
-
- private void reloadBlacklist() {
- synchronized (mLock) {
- reloadBlacklistLocked();
- }
- }
-
- /**
- * Return true if in blacklist
- * (package name matches blacklist, and does not match whitelist)
- */
- public boolean isBlacklisted(String packageName) {
- synchronized (mLock) {
- for (String black : mBlacklist) {
- if (packageName.startsWith(black)) {
- if (inWhitelist(packageName)) {
- continue;
- } else {
- if (D) Log.d(TAG, "dropping location (blacklisted): "
- + packageName + " matches " + black);
- return true;
- }
- }
- }
- }
- return false;
- }
-
- /**
- * Return true if any of packages are in whitelist
- */
- private boolean inWhitelist(String pkg) {
- synchronized (mLock) {
- for (String white : mWhitelist) {
- if (pkg.startsWith(white)) return true;
- }
- }
- return false;
- }
-
- @Override
- public void onChange(boolean selfChange) {
- reloadBlacklist();
- }
-
- public void switchUser(int userId) {
- synchronized(mLock) {
- mCurrentUserId = userId;
- reloadBlacklistLocked();
- }
- }
-
- private String[] getStringArrayLocked(String key) {
- String flatString;
- synchronized(mLock) {
- flatString = Settings.Secure.getStringForUser(mContext.getContentResolver(), key,
- mCurrentUserId);
- }
- if (flatString == null) {
- return new String[0];
- }
- String[] splitStrings = flatString.split(",");
- ArrayList<String> result = new ArrayList<String>();
- for (String pkg : splitStrings) {
- pkg = pkg.trim();
- if (pkg.isEmpty()) {
- continue;
- }
- result.add(pkg);
- }
- return result.toArray(new String[result.size()]);
- }
-
- public void dump(PrintWriter pw) {
- pw.println("mWhitelist=" + Arrays.toString(mWhitelist) + " mBlacklist=" +
- Arrays.toString(mBlacklist));
- }
-}
diff --git a/services/core/java/com/android/server/location/LocationSettingsStore.java b/services/core/java/com/android/server/location/LocationSettingsStore.java
new file mode 100644
index 0000000..a4b6d97
--- /dev/null
+++ b/services/core/java/com/android/server/location/LocationSettingsStore.java
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.location;
+
+import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS;
+import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST;
+import static android.provider.Settings.Global.LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS;
+import static android.provider.Settings.Global.LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST;
+import static android.provider.Settings.Global.LOCATION_LAST_LOCATION_MAX_AGE_MILLIS;
+import static android.provider.Settings.Secure.LOCATION_MODE;
+import static android.provider.Settings.Secure.LOCATION_MODE_OFF;
+import static android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.text.TextUtils;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Provides accessors and listeners for all location related settings.
+ */
+public class LocationSettingsStore {
+
+ private static final String LOCATION_PACKAGE_BLACKLIST = "locationPackagePrefixBlacklist";
+ private static final String LOCATION_PACKAGE_WHITELIST = "locationPackagePrefixWhitelist";
+
+ private static final long DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS = 30 * 60 * 1000;
+ private static final long DEFAULT_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS =
+ 30 * 60 * 1000;
+ private static final long DEFAULT_MAX_LAST_LOCATION_AGE_MS = 20 * 60 * 1000;
+
+ private final Context mContext;
+
+ private final IntegerSecureSetting mLocationMode;
+ private final StringListCachedSecureSetting mLocationProvidersAllowed;
+ private final LongGlobalSetting mBackgroundThrottleIntervalMs;
+ private final StringListCachedSecureSetting mLocationPackageBlacklist;
+ private final StringListCachedSecureSetting mLocationPackageWhitelist;
+ private final StringListCachedGlobalSetting mBackgroundThrottlePackageWhitelist;
+ private final StringListCachedGlobalSetting mIgnoreSettingsPackageWhitelist;
+
+ public LocationSettingsStore(Context context, Handler handler) {
+ mContext = context;
+
+ mLocationMode = new IntegerSecureSetting(context, LOCATION_MODE, handler);
+ mLocationProvidersAllowed = new StringListCachedSecureSetting(context,
+ LOCATION_PROVIDERS_ALLOWED, handler);
+ mBackgroundThrottleIntervalMs = new LongGlobalSetting(context,
+ LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS, handler);
+ mLocationPackageBlacklist = new StringListCachedSecureSetting(context,
+ LOCATION_PACKAGE_BLACKLIST, handler);
+ mLocationPackageWhitelist = new StringListCachedSecureSetting(context,
+ LOCATION_PACKAGE_WHITELIST, handler);
+ mBackgroundThrottlePackageWhitelist = new StringListCachedGlobalSetting(context,
+ LOCATION_BACKGROUND_THROTTLE_PACKAGE_WHITELIST, handler);
+ mIgnoreSettingsPackageWhitelist = new StringListCachedGlobalSetting(context,
+ LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST, handler);
+ }
+
+ /**
+ * Retrieve if location is enabled or not.
+ */
+ public boolean isLocationEnabled(int userId) {
+ return mLocationMode.getValueForUser(LOCATION_MODE_OFF, userId) != LOCATION_MODE_OFF;
+ }
+
+ /**
+ * Add a listener for changes to the location enabled setting.
+ */
+ public void addOnLocationEnabledChangedListener(Runnable listener) {
+ mLocationMode.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the location enabled setting.
+ */
+ public void removeOnLocationEnabledChangedListener(Runnable listener) {
+ mLocationMode.addListener(listener);
+ }
+
+ /**
+ * Retrieve the currently allowed location providers.
+ */
+ public List<String> getLocationProvidersAllowed(int userId) {
+ return mLocationProvidersAllowed.getValueForUser(userId);
+ }
+
+ /**
+ * Add a listener for changes to the currently allowed location providers.
+ */
+ public void addOnLocationProvidersAllowedChangedListener(Runnable runnable) {
+ mLocationProvidersAllowed.addListener(runnable);
+ }
+
+ /**
+ * Remove a listener for changes to the currently allowed location providers.
+ */
+ public void removeOnLocationProvidersAllowedChangedListener(Runnable runnable) {
+ mLocationProvidersAllowed.removeListener(runnable);
+ }
+
+ /**
+ * Retrieve the background throttle interval.
+ */
+ public long getBackgroundThrottleIntervalMs() {
+ return mBackgroundThrottleIntervalMs.getValue(DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
+ }
+
+ /**
+ * Add a listener for changes to the background throttle interval.
+ */
+ public void addOnBackgroundThrottleIntervalChangedListener(Runnable listener) {
+ mBackgroundThrottleIntervalMs.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the background throttle interval.
+ */
+ public void removeOnBackgroundThrottleIntervalChangedListener(Runnable listener) {
+ mBackgroundThrottleIntervalMs.removeListener(listener);
+ }
+
+ /**
+ * Check if the given package is blacklisted for location access.
+ */
+ public boolean isLocationPackageBlacklisted(int userId, String packageName) {
+ List<String> locationPackageBlacklist = mLocationPackageBlacklist.getValueForUser(userId);
+ if (locationPackageBlacklist.isEmpty()) {
+ return false;
+ }
+
+ List<String> locationPackageWhitelist = mLocationPackageWhitelist.getValueForUser(userId);
+ for (String locationWhitelistPackage : locationPackageWhitelist) {
+ if (packageName.startsWith(locationWhitelistPackage)) {
+ return false;
+ }
+ }
+
+ for (String locationBlacklistPackage : locationPackageBlacklist) {
+ if (packageName.startsWith(locationBlacklistPackage)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Retrieve the background throttle package whitelist.
+ */
+ public List<String> getBackgroundThrottlePackageWhitelist() {
+ return mBackgroundThrottlePackageWhitelist.getValue();
+ }
+
+ /**
+ * Add a listener for changes to the background throttle package whitelist.
+ */
+ public void addOnBackgroundThrottlePackageWhitelistChangedListener(Runnable listener) {
+ mBackgroundThrottlePackageWhitelist.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the background throttle package whitelist.
+ */
+ public void removeOnBackgroundThrottlePackageWhitelistChangedListener(Runnable listener) {
+ mBackgroundThrottlePackageWhitelist.removeListener(listener);
+ }
+
+ /**
+ * Retrieve the ignore settings package whitelist.
+ */
+ public List<String> getIgnoreSettingsPackageWhitelist() {
+ return mIgnoreSettingsPackageWhitelist.getValue();
+ }
+
+ /**
+ * Add a listener for changes to the ignore settings package whitelist.
+ */
+ public void addOnIgnoreSettingsPackageWhitelistChangedListener(Runnable listener) {
+ mIgnoreSettingsPackageWhitelist.addListener(listener);
+ }
+
+ /**
+ * Remove a listener for changes to the ignore settings package whitelist.
+ */
+ public void removeOnIgnoreSettingsPackageWhitelistChangedListener(Runnable listener) {
+ mIgnoreSettingsPackageWhitelist.removeListener(listener);
+ }
+
+ /**
+ * Retrieve the background throttling proximity alert interval.
+ */
+ public long getBackgroundThrottleProximityAlertIntervalMs() {
+ return Settings.Global.getLong(mContext.getContentResolver(),
+ LOCATION_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS,
+ DEFAULT_BACKGROUND_THROTTLE_PROXIMITY_ALERT_INTERVAL_MS);
+ }
+
+ public long getMaxLastLocationAgeMs() {
+ return Settings.Global.getLong(
+ mContext.getContentResolver(),
+ LOCATION_LAST_LOCATION_MAX_AGE_MILLIS,
+ DEFAULT_MAX_LAST_LOCATION_AGE_MS);
+ }
+
+ /**
+ * Dump info for debugging.
+ */
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ int userId = ActivityManager.getCurrentUser();
+
+ ipw.println("--Location Settings--");
+ ipw.increaseIndent();
+
+ ipw.print("Location Enabled: ");
+ ipw.println(isLocationEnabled(userId));
+
+ ipw.print("Location Providers Allowed: ");
+ ipw.println(getLocationProvidersAllowed(userId));
+
+ List<String> locationPackageBlacklist = mLocationPackageBlacklist.getValueForUser(userId);
+ if (!locationPackageBlacklist.isEmpty()) {
+ ipw.println("Location Blacklisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : locationPackageBlacklist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+
+ List<String> locationPackageWhitelist = mLocationPackageWhitelist.getValueForUser(
+ userId);
+ if (!locationPackageWhitelist.isEmpty()) {
+ ipw.println("Location Whitelisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : locationPackageWhitelist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+ }
+ }
+
+ List<String> backgroundThrottlePackageWhitelist =
+ mBackgroundThrottlePackageWhitelist.getValue();
+ if (!backgroundThrottlePackageWhitelist.isEmpty()) {
+ ipw.println("Throttling Whitelisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : backgroundThrottlePackageWhitelist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+ }
+
+ List<String> ignoreSettingsPackageWhitelist = mIgnoreSettingsPackageWhitelist.getValue();
+ if (!ignoreSettingsPackageWhitelist.isEmpty()) {
+ ipw.println("Bypass Whitelisted Packages:");
+ ipw.increaseIndent();
+ for (String packageName : ignoreSettingsPackageWhitelist) {
+ ipw.println(packageName);
+ }
+ ipw.decreaseIndent();
+ }
+ }
+
+ private abstract static class ObservingSetting extends ContentObserver {
+
+ private final CopyOnWriteArrayList<Runnable> mListeners;
+
+ private ObservingSetting(Context context, String settingName, Handler handler) {
+ super(handler);
+ mListeners = new CopyOnWriteArrayList<>();
+
+ context.getContentResolver().registerContentObserver(
+ getUriFor(settingName), false, this, UserHandle.USER_ALL);
+ }
+
+ public void addListener(Runnable listener) {
+ mListeners.add(listener);
+ }
+
+ public void removeListener(Runnable listener) {
+ mListeners.remove(listener);
+ }
+
+ protected abstract Uri getUriFor(String settingName);
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ for (Runnable listener : mListeners) {
+ listener.run();
+ }
+ }
+ }
+
+ private static class IntegerSecureSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private IntegerSecureSetting(Context context, String settingName, Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public int getValueForUser(int defaultValue, int userId) {
+ return Settings.Secure.getIntForUser(mContext.getContentResolver(), mSettingName,
+ defaultValue, userId);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Secure.getUriFor(settingName);
+ }
+ }
+
+ private static class StringListCachedSecureSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private int mCachedUserId = UserHandle.USER_NULL;
+ private List<String> mCachedValue;
+
+ private StringListCachedSecureSetting(Context context, String settingName,
+ Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public synchronized List<String> getValueForUser(int userId) {
+ if (userId != mCachedUserId) {
+ String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(),
+ mSettingName, userId);
+ if (TextUtils.isEmpty(setting)) {
+ mCachedValue = Collections.emptyList();
+ } else {
+ mCachedValue = Arrays.asList(setting.split(","));
+ }
+ mCachedUserId = userId;
+ }
+
+ return mCachedValue;
+ }
+
+ public synchronized void invalidateForUser(int userId) {
+ if (mCachedUserId == userId) {
+ mCachedUserId = UserHandle.USER_NULL;
+ mCachedValue = null;
+ }
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ invalidateForUser(userId);
+ super.onChange(selfChange, uri, userId);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Secure.getUriFor(settingName);
+ }
+ }
+
+ private static class LongGlobalSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private LongGlobalSetting(Context context, String settingName, Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public long getValue(long defaultValue) {
+ return Settings.Global.getLong(mContext.getContentResolver(), mSettingName,
+ defaultValue);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Global.getUriFor(settingName);
+ }
+ }
+
+ private static class StringListCachedGlobalSetting extends ObservingSetting {
+
+ private final Context mContext;
+ private final String mSettingName;
+
+ private boolean mValid;
+ private List<String> mCachedValue;
+
+ private StringListCachedGlobalSetting(Context context, String settingName,
+ Handler handler) {
+ super(context, settingName, handler);
+ mContext = context;
+ mSettingName = settingName;
+ }
+
+ public synchronized List<String> getValue() {
+ if (!mValid) {
+ String setting = Settings.Global.getString(mContext.getContentResolver(),
+ mSettingName);
+ if (TextUtils.isEmpty(setting)) {
+ mCachedValue = Collections.emptyList();
+ } else {
+ mCachedValue = Arrays.asList(setting.split(","));
+ }
+ mValid = true;
+ }
+
+ return mCachedValue;
+ }
+
+ public synchronized void invalidate() {
+ mValid = false;
+ mCachedValue = null;
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri, int userId) {
+ invalidate();
+ super.onChange(selfChange, uri, userId);
+ }
+
+ @Override
+ protected Uri getUriFor(String settingName) {
+ return Settings.Global.getUriFor(settingName);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
index 4816ceb..626bf1c 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderProxy.java
@@ -119,6 +119,11 @@
}
}
+ @NonNull
+ public String getUniqueId() {
+ return mUniqueId;
+ }
+
@Nullable
public MediaRoute2ProviderInfo getProviderInfo() {
return mProviderInfo;
@@ -294,7 +299,7 @@
}
public interface Callback {
- void onProviderStateChanged(MediaRoute2ProviderProxy provider);
+ void onProviderStateChanged(@NonNull MediaRoute2ProviderProxy provider);
}
private final class Connection implements DeathRecipient {
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 361dc36..44642d4 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -47,9 +47,12 @@
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
* TODO: Merge this to MediaRouterService once it's finished.
@@ -357,8 +360,7 @@
mAllClientRecords.put(binder, clientRecord);
userRecord.mHandler.sendMessage(
- obtainMessage(UserHandler::notifyProviderInfosUpdatedToClient,
- userRecord.mHandler, client));
+ obtainMessage(UserHandler::notifyRoutesToClient, userRecord.mHandler, client));
}
}
@@ -586,6 +588,7 @@
final class UserRecord {
public final int mUserId;
+ //TODO: make records private for thread-safety
final ArrayList<ClientRecord> mClientRecords = new ArrayList<>();
final ArrayList<ManagerRecord> mManagerRecords = new ArrayList<>();
final UserHandler mHandler;
@@ -705,7 +708,7 @@
//TODO: Make this thread-safe.
private final ArrayList<MediaRoute2ProviderProxy> mMediaProviders =
new ArrayList<>();
- private List<MediaRoute2ProviderInfo> mProviderInfos;
+ private final List<MediaRoute2ProviderInfo> mProviderInfos = new ArrayList<>();
private boolean mRunning;
private boolean mProviderInfosUpdateScheduled;
@@ -745,14 +748,89 @@
}
@Override
- public void onProviderStateChanged(MediaRoute2ProviderProxy provider) {
- updateProvider(provider);
+ public void onProviderStateChanged(@NonNull MediaRoute2ProviderProxy provider) {
+ sendMessage(PooledLambda.obtainMessage(UserHandler::updateProvider, this, provider));
}
private void updateProvider(MediaRoute2ProviderProxy provider) {
+ int providerIndex = getProviderInfoIndex(provider.getUniqueId());
+ MediaRoute2ProviderInfo providerInfo = provider.getProviderInfo();
+ MediaRoute2ProviderInfo prevInfo =
+ (providerIndex < 0) ? null : mProviderInfos.get(providerIndex);
+
+ if (Objects.equals(prevInfo, providerInfo)) return;
+
+ if (prevInfo == null) {
+ mProviderInfos.add(providerInfo);
+ Collection<MediaRoute2Info> addedRoutes = providerInfo.getRoutes();
+ if (addedRoutes.size() > 0) {
+ sendMessage(PooledLambda.obtainMessage(UserHandler::notifyRoutesAddedToClients,
+ this, getClients(), new ArrayList<>(addedRoutes)));
+ }
+ } else if (providerInfo == null) {
+ mProviderInfos.remove(prevInfo);
+ Collection<MediaRoute2Info> removedRoutes = prevInfo.getRoutes();
+ if (removedRoutes.size() > 0) {
+ sendMessage(PooledLambda.obtainMessage(
+ UserHandler::notifyRoutesRemovedToClients,
+ this, getClients(), new ArrayList<>(removedRoutes)));
+ }
+ } else {
+ mProviderInfos.set(providerIndex, providerInfo);
+ List<MediaRoute2Info> addedRoutes = new ArrayList<>();
+ List<MediaRoute2Info> removedRoutes = new ArrayList<>();
+ List<MediaRoute2Info> changedRoutes = new ArrayList<>();
+
+ final Collection<MediaRoute2Info> currentRoutes = providerInfo.getRoutes();
+ final Set<String> updatedRouteIds = new HashSet<>();
+
+ for (MediaRoute2Info route : currentRoutes) {
+ if (!route.isValid()) {
+ Slog.w(TAG, "Ignoring invalid route : " + route);
+ continue;
+ }
+ MediaRoute2Info prevRoute = prevInfo.getRoute(route.getId());
+
+ if (prevRoute != null) {
+ if (!Objects.equals(prevRoute, route)) {
+ changedRoutes.add(route);
+ }
+ updatedRouteIds.add(route.getId());
+ } else {
+ addedRoutes.add(route);
+ }
+ }
+
+ for (MediaRoute2Info prevRoute : prevInfo.getRoutes()) {
+ if (!updatedRouteIds.contains(prevRoute.getId())) {
+ removedRoutes.add(prevRoute);
+ }
+ }
+
+ List<IMediaRouter2Client> clients = getClients();
+ if (addedRoutes.size() > 0) {
+ notifyRoutesAddedToClients(clients, addedRoutes);
+ }
+ if (removedRoutes.size() > 0) {
+ notifyRoutesRemovedToClients(clients, removedRoutes);
+ }
+ if (changedRoutes.size() > 0) {
+ notifyRoutesChangedToClients(clients, changedRoutes);
+ }
+ }
scheduleUpdateProviderInfos();
}
+ private int getProviderInfoIndex(String providerId) {
+ for (int i = 0; i < mProviderInfos.size(); i++) {
+ MediaRoute2ProviderInfo providerInfo = mProviderInfos.get(i);
+ if (TextUtils.equals(providerInfo.getUniqueId(), providerId)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
private void selectRoute(ClientRecord clientRecord, MediaRoute2Info route) {
if (route != null) {
MediaRoute2ProviderProxy provider = findProvider(route.getProviderId());
@@ -803,6 +881,7 @@
}
}
+ //TODO: should be replaced into notifyRoutes...ToManagers
private void updateProviderInfos() {
mProviderInfosUpdateScheduled = false;
@@ -810,55 +889,83 @@
if (service == null) {
return;
}
- final List<MediaRoute2ProviderInfo> providers = new ArrayList<>();
- for (MediaRoute2ProviderProxy mediaProvider : mMediaProviders) {
- final MediaRoute2ProviderInfo providerInfo =
- mediaProvider.getProviderInfo();
- if (providerInfo == null || !providerInfo.isValid()) {
- Slog.w(TAG, "Ignoring invalid provider info : " + providerInfo);
- } else {
- providers.add(providerInfo);
- }
- }
- mProviderInfos = providers;
final List<IMediaRouter2Manager> managers = new ArrayList<>();
- final List<IMediaRouter2Client> clients = new ArrayList<>();
synchronized (service.mLock) {
for (ManagerRecord managerRecord : mUserRecord.mManagerRecords) {
managers.add(managerRecord.mManager);
}
+ }
+ for (IMediaRouter2Manager manager : managers) {
+ notifyProviderInfosUpdatedToManager(manager);
+ }
+ }
+
+ private List<IMediaRouter2Client> getClients() {
+ final List<IMediaRouter2Client> clients = new ArrayList<>();
+ MediaRouter2ServiceImpl service = mServiceRef.get();
+ if (service == null) {
+ return clients;
+ }
+ synchronized (service.mLock) {
for (ClientRecord clientRecord : mUserRecord.mClientRecords) {
if (clientRecord instanceof Client2Record) {
clients.add(((Client2Record) clientRecord).mClient);
}
}
}
- for (IMediaRouter2Manager manager : managers) {
- notifyProviderInfosUpdatedToManager(manager);
- }
- for (IMediaRouter2Client client : clients) {
- notifyProviderInfosUpdatedToClient(client);
- }
+ return clients;
}
- private void notifyProviderInfosUpdatedToClient(IMediaRouter2Client client) {
- if (mProviderInfos == null) {
- scheduleUpdateProviderInfos();
+ private void notifyRoutesToClient(IMediaRouter2Client client) {
+ List<MediaRoute2Info> routes = new ArrayList<>();
+ for (MediaRoute2ProviderInfo providerInfo : mProviderInfos) {
+ routes.addAll(providerInfo.getRoutes());
+ }
+ if (routes.size() == 0) {
return;
}
try {
- client.notifyProviderInfosUpdated(mProviderInfos);
+ client.notifyRoutesAdded(routes);
} catch (RemoteException ex) {
- Slog.w(TAG, "Failed to notify provider infos updated. Client probably died.");
+ Slog.w(TAG, "Failed to notify all routes. Client probably died.", ex);
+ }
+ }
+
+ private void notifyRoutesAddedToClients(List<IMediaRouter2Client> clients,
+ List<MediaRoute2Info> routes) {
+ for (IMediaRouter2Client client : clients) {
+ try {
+ client.notifyRoutesAdded(routes);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify routes added. Client probably died.", ex);
+ }
+ }
+ }
+
+ private void notifyRoutesRemovedToClients(List<IMediaRouter2Client> clients,
+ List<MediaRoute2Info> routes) {
+ for (IMediaRouter2Client client : clients) {
+ try {
+ client.notifyRoutesRemoved(routes);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify routes removed. Client probably died.", ex);
+ }
+ }
+ }
+
+ private void notifyRoutesChangedToClients(List<IMediaRouter2Client> clients,
+ List<MediaRoute2Info> routes) {
+ for (IMediaRouter2Client client : clients) {
+ try {
+ client.notifyRoutesChanged(routes);
+ } catch (RemoteException ex) {
+ Slog.w(TAG, "Failed to notify routes changed. Client probably died.", ex);
+ }
}
}
private void notifyProviderInfosUpdatedToManager(IMediaRouter2Manager manager) {
- if (mProviderInfos == null) {
- scheduleUpdateProviderInfos();
- return;
- }
try {
manager.notifyProviderInfosUpdated(mProviderInfos);
} catch (RemoteException ex) {
@@ -891,9 +998,7 @@
private MediaRoute2ProviderProxy findProvider(String providerId) {
for (MediaRoute2ProviderProxy provider : mMediaProviders) {
- final MediaRoute2ProviderInfo providerInfo = provider.getProviderInfo();
- if (providerInfo != null
- && TextUtils.equals(providerInfo.getUniqueId(), providerId)) {
+ if (TextUtils.equals(provider.getUniqueId(), providerId)) {
return provider;
}
}
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 193e0af..c25e206 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -1316,7 +1316,6 @@
* pressed.
*
* @param packageName The caller's package name, obtained by Context#getPackageName()
- * @param opPackageName The caller's op package name, obtained by Context#getOpPackageName()
* @param sessionToken token for the session that the controller is pointing to
* @param keyEvent media key event
* @see #dispatchVolumeKeyEvent
@@ -1330,15 +1329,15 @@
try {
synchronized (mLock) {
MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken);
- if (record == null) {
- Log.w(TAG, "Failed to find session to dispatch key event.");
- return false;
- }
- if (DEBUG) {
+ if (DEBUG_KEY_EVENT) {
Log.d(TAG, "dispatchMediaKeyEventToSessionAsSystemService, pkg="
+ packageName + ", pid=" + pid + ", uid=" + uid + ", sessionToken="
+ sessionToken + ", event=" + keyEvent + ", session=" + record);
}
+ if (record == null) {
+ Log.w(TAG, "Failed to find session to dispatch key event.");
+ return false;
+ }
return record.sendMediaButton(packageName, pid, uid, true /* asSystemService */,
keyEvent, 0, null);
}
@@ -1688,6 +1687,12 @@
try {
synchronized (mLock) {
MediaSessionRecord record = getMediaSessionRecordLocked(sessionToken);
+ if (DEBUG_KEY_EVENT) {
+ Log.d(TAG, "dispatchVolumeKeyEventToSessionAsSystemService, pkg="
+ + packageName + ", opPkg=" + opPackageName + ", pid=" + pid
+ + ", uid=" + uid + ", sessionToken=" + sessionToken + ", event="
+ + keyEvent + ", session=" + record);
+ }
if (record == null) {
Log.w(TAG, "Failed to find session to dispatch key event, token="
+ sessionToken + ". Fallbacks to the default handling.");
@@ -1695,12 +1700,6 @@
keyEvent, AudioManager.USE_DEFAULT_STREAM_TYPE, false);
return;
}
- if (DEBUG) {
- Log.d(TAG, "dispatchVolumeKeyEventToSessionAsSystemService, pkg="
- + packageName + ", opPkg=" + opPackageName + ", pid=" + pid
- + ", uid=" + uid + ", sessionToken=" + sessionToken + ", event="
- + keyEvent + ", session=" + record);
- }
switch (keyEvent.getAction()) {
case KeyEvent.ACTION_DOWN: {
int direction = 0;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 388214b..32d4b72 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -912,7 +912,8 @@
}
final private IUidObserver mUidObserver = new IUidObserver.Stub() {
- @Override public void onUidStateChanged(int uid, int procState, long procStateSeq) {
+ @Override public void onUidStateChanged(int uid, int procState, long procStateSeq,
+ int capability) {
mUidEventHandler.obtainMessage(UID_MSG_STATE_CHANGED,
uid, procState, procStateSeq).sendToTarget();
}
diff --git a/services/core/java/com/android/server/notification/InlineReplyUriRecord.java b/services/core/java/com/android/server/notification/InlineReplyUriRecord.java
new file mode 100644
index 0000000..76cfb03
--- /dev/null
+++ b/services/core/java/com/android/server/notification/InlineReplyUriRecord.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.util.ArraySet;
+
+/**
+ * A record of inline reply (ex. RemoteInput) URI grants associated with a Notification.
+ */
+public final class InlineReplyUriRecord {
+ private final IBinder mPermissionOwner;
+ private final ArraySet<Uri> mUris;
+ private final UserHandle mUser;
+ private final String mPackageName;
+ private final String mKey;
+
+ /**
+ * Construct a new InlineReplyUriRecord.
+ * @param owner The PermissionOwner associated with this record.
+ * @param user The user associated with this record.
+ * @param packageName The name of the package which posted the notification.
+ * @param key The key of the original NotificationRecord this notification as created with.
+ */
+ public InlineReplyUriRecord(IBinder owner, UserHandle user, String packageName, String key) {
+ mPermissionOwner = owner;
+ mUris = new ArraySet<>();
+ mUser = user;
+ mPackageName = packageName;
+ mKey = key;
+ }
+
+ /**
+ * Get the permission owner associated with this record.
+ */
+ public IBinder getPermissionOwner() {
+ return mPermissionOwner;
+ }
+
+ /**
+ * Get the content URIs associated with this record.
+ */
+ public ArraySet<Uri> getUris() {
+ return mUris;
+ }
+
+ /**
+ * Associate a new content URI with this record.
+ */
+ public void addUri(Uri uri) {
+ mUris.add(uri);
+ }
+
+ /**
+ * Get the user id associated with this record.
+ * If the UserHandle associated with this record belongs to USER_ALL, return the ID for
+ * USER_SYSTEM instead, to avoid errors around modifying URI permissions for an invalid user ID.
+ */
+ public int getUserId() {
+ int userId = mUser.getIdentifier();
+ if (userId == UserHandle.USER_ALL) {
+ return UserHandle.USER_SYSTEM;
+ } else {
+ return userId;
+ }
+ }
+
+ /**
+ * Get the name of the package associated with this record.
+ */
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
+ * Get the key associated with this record.
+ */
+ public String getKey() {
+ return mKey;
+ }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 6f0ad33..88fc072 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -18,6 +18,7 @@
import android.app.Notification;
import android.net.Uri;
+import android.os.UserHandle;
import android.service.notification.NotificationStats;
import com.android.internal.statusbar.NotificationVisibility;
@@ -53,7 +54,13 @@
* Grant permission to read the specified URI to the package associated with the
* NotificationRecord associated with the given key.
*/
- void grantInlineReplyUriPermission(String key, Uri uri, int callingUid);
+ void grantInlineReplyUriPermission(String key, Uri uri, UserHandle user, String packageName,
+ int callingUid);
+
+ /**
+ * Clear inline URI grants associated with the given notification.
+ */
+ void clearInlineReplyUriPermissions(String key, int callingUid);
/**
* Notifies that smart replies and actions have been added to the UI.
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0fc1718..5e76401 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -415,6 +415,8 @@
@GuardedBy("mNotificationLock")
final ArrayMap<String, NotificationRecord> mNotificationsByKey = new ArrayMap<>();
@GuardedBy("mNotificationLock")
+ final ArrayMap<String, InlineReplyUriRecord> mInlineReplyRecordsByKey = new ArrayMap<>();
+ @GuardedBy("mNotificationLock")
final ArrayList<NotificationRecord> mEnqueuedNotifications = new ArrayList<>();
@GuardedBy("mNotificationLock")
final ArrayMap<Integer, ArrayMap<String, String>> mAutobundledSummaries = new ArrayMap<>();
@@ -1167,42 +1169,53 @@
* user associated with the NotificationRecord, and this grant will fail when trying
* to grant URI permissions across users.
*/
- public void grantInlineReplyUriPermission(String key, Uri uri, int callingUid) {
+ public void grantInlineReplyUriPermission(String key, Uri uri, UserHandle user,
+ String packageName, int callingUid) {
synchronized (mNotificationLock) {
- NotificationRecord r = mNotificationsByKey.get(key);
- if (r != null) {
- IBinder owner = r.permissionOwner;
- if (owner == null) {
- r.permissionOwner = mUgmInternal.newUriPermissionOwner("NOTIF:" + key);
- owner = r.permissionOwner;
- }
- int uid = callingUid;
- int userId = r.sbn.getUserId();
- if (userId == UserHandle.USER_ALL) {
- userId = USER_SYSTEM;
- }
- if (UserHandle.getUserId(uid) != userId) {
- try {
- final String[] pkgs = mPackageManager.getPackagesForUid(callingUid);
- if (pkgs == null) {
- Log.e(TAG, "Cannot grant uri permission to unknown UID: "
- + callingUid);
- }
- final String pkg = pkgs[0]; // Get the SystemUI package
- // Find the UID for SystemUI for the correct user
- uid = mPackageManager.getPackageUid(pkg, 0, userId);
- } catch (RemoteException re) {
- Log.e(TAG, "Cannot talk to package manager", re);
+ InlineReplyUriRecord r = mInlineReplyRecordsByKey.get(key);
+ if (r == null) {
+ InlineReplyUriRecord newRecord = new InlineReplyUriRecord(
+ mUgmInternal.newUriPermissionOwner("INLINE_REPLY:" + key),
+ user,
+ packageName,
+ key);
+ r = newRecord;
+ mInlineReplyRecordsByKey.put(key, r);
+ }
+ IBinder owner = r.getPermissionOwner();
+ int uid = callingUid;
+ int userId = r.getUserId();
+ if (UserHandle.getUserId(uid) != userId) {
+ try {
+ final String[] pkgs = mPackageManager.getPackagesForUid(callingUid);
+ if (pkgs == null) {
+ Log.e(TAG, "Cannot grant uri permission to unknown UID: "
+ + callingUid);
}
+ final String pkg = pkgs[0]; // Get the SystemUI package
+ // Find the UID for SystemUI for the correct user
+ uid = mPackageManager.getPackageUid(pkg, 0, userId);
+ } catch (RemoteException re) {
+ Log.e(TAG, "Cannot talk to package manager", re);
}
- grantUriPermission(owner, uri, uid, r.sbn.getPackageName(), userId);
- } else {
- Log.w(TAG, "No record found for notification key:" + key);
+ }
+ r.addUri(uri);
+ grantUriPermission(owner, uri, uid, r.getPackageName(), userId);
+ }
+ }
- // TODO: figure out cancel story. I think it's: sysui needs to tell us
- // whenever noitifications held by a lifetimextender go away
- // IBinder owner = mUgmInternal.newUriPermissionOwner("InlineReply:" + key);
- // pass in userId and package as well as key (key for logging purposes)
+ @Override
+ /**
+ * Clears inline URI permission grants by destroying the permission owner for the specified
+ * notification.
+ */
+ public void clearInlineReplyUriPermissions(String key, int callingUid) {
+ synchronized (mNotificationLock) {
+ InlineReplyUriRecord uriRecord = mInlineReplyRecordsByKey.get(key);
+ if (uriRecord != null) {
+ destroyPermissionOwner(uriRecord.getPermissionOwner(), uriRecord.getUserId(),
+ "INLINE_REPLY: " + uriRecord.getKey());
+ mInlineReplyRecordsByKey.remove(key);
}
}
}
@@ -7036,15 +7049,8 @@
// If we have no Uris to grant, but an existing owner, go destroy it
if (newUris == null && permissionOwner != null) {
- final long ident = Binder.clearCallingIdentity();
- try {
- if (DBG) Slog.d(TAG, key + ": destroying owner");
- mUgmInternal.revokeUriPermissionFromOwner(permissionOwner, null, ~0,
- UserHandle.getUserId(oldRecord.getUid()));
- permissionOwner = null;
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ destroyPermissionOwner(permissionOwner, UserHandle.getUserId(oldRecord.getUid()), key);
+ permissionOwner = null;
}
// Grant access to new Uris
@@ -7065,7 +7071,9 @@
final Uri uri = oldUris.valueAt(i);
if (newUris == null || !newUris.contains(uri)) {
if (DBG) Slog.d(TAG, key + ": revoking " + uri);
- revokeUriPermission(permissionOwner, uri, oldRecord.getUid());
+ int userId = ContentProvider.getUserIdFromUri(
+ uri, UserHandle.getUserId(oldRecord.getUid()));
+ revokeUriPermission(permissionOwner, uri, userId);
}
}
}
@@ -7092,7 +7100,7 @@
}
}
- private void revokeUriPermission(IBinder owner, Uri uri, int sourceUid) {
+ private void revokeUriPermission(IBinder owner, Uri uri, int userId) {
if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return;
final long ident = Binder.clearCallingIdentity();
@@ -7101,7 +7109,17 @@
owner,
ContentProvider.getUriWithoutUserId(uri),
Intent.FLAG_GRANT_READ_URI_PERMISSION,
- ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(sourceUid)));
+ userId);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ private void destroyPermissionOwner(IBinder owner, int userId, String logKey) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ if (DBG) Slog.d(TAG, logKey + ": destroying owner");
+ mUgmInternal.revokeUriPermissionFromOwner(owner, null, ~0, userId);
} finally {
Binder.restoreCallingIdentity(ident);
}
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index dc0cd18..5195a52 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -211,7 +211,7 @@
final Uri data = intent.getData();
if ("content".equalsIgnoreCase(intent.getScheme())
&& data != null
- && providerInfo.authority.equalsIgnoreCase(data.getAuthority())) {
+ && Objects.equals(providerInfo.authority, data.getAuthority())) {
return true;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b36958a..936d88d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -751,17 +751,17 @@
static final List<SystemPartition> SYSTEM_PARTITIONS = Collections.unmodifiableList(
Arrays.asList(
new SystemPartition(Environment.getRootDirectory(), 0 /* scanFlag */,
- true /* hasPriv */, false /* hasOverlays */),
+ false /* hasOverlays */),
new SystemPartition(Environment.getVendorDirectory(), SCAN_AS_VENDOR,
- true /* hasPriv */, true /* hasOverlays */),
+ true /* hasOverlays */),
new SystemPartition(Environment.getOdmDirectory(), SCAN_AS_ODM,
- true /* hasPriv */, true /* hasOverlays */),
+ true /* hasOverlays */),
new SystemPartition(Environment.getOemDirectory(), SCAN_AS_OEM,
- false /* hasPriv */, true /* hasOverlays */),
+ true /* hasOverlays */),
new SystemPartition(Environment.getProductDirectory(), SCAN_AS_PRODUCT,
- true /* hasPriv */, true /* hasOverlays */),
+ true /* hasOverlays */),
new SystemPartition(Environment.getSystemExtDirectory(), SCAN_AS_SYSTEM_EXT,
- true /* hasPriv */, true /* hasOverlays */)));
+ true /* hasOverlays */)));
private final List<SystemPartition> mDirsToScanAsSystem;
@@ -2427,12 +2427,28 @@
@Nullable
public final File overlayFolder;
- private SystemPartition(File folder, int scanFlag, boolean hasPrivApps,
- boolean hasOverlays) {
+
+ private static boolean shouldScanPrivApps(@ScanFlags int scanFlags) {
+ if ((scanFlags & SCAN_AS_OEM) != 0) {
+ return false;
+ }
+ if (scanFlags == 0) { // /system partition
+ return true;
+ }
+ if ((scanFlags
+ & (SCAN_AS_VENDOR | SCAN_AS_ODM | SCAN_AS_PRODUCT | SCAN_AS_SYSTEM_EXT)) != 0) {
+ return true;
+ }
+ return false;
+ }
+
+ private SystemPartition(File folder, int scanFlag, boolean hasOverlays) {
this.folder = folder;
this.scanFlag = scanFlag;
this.appFolder = toCanonical(new File(folder, "app"));
- this.privAppFolder = hasPrivApps ? toCanonical(new File(folder, "priv-app")) : null;
+ this.privAppFolder = shouldScanPrivApps(scanFlag)
+ ? toCanonical(new File(folder, "priv-app"))
+ : null;
this.overlayFolder = hasOverlays ? toCanonical(new File(folder, "overlay")) : null;
}
@@ -8663,6 +8679,16 @@
pkgSetting = originalPkgSetting == null ? installedPkgSetting : originalPkgSetting;
pkgAlreadyExists = pkgSetting != null;
final String disabledPkgName = pkgAlreadyExists ? pkgSetting.name : pkg.packageName;
+ if (scanSystemPartition && !pkgAlreadyExists
+ && mSettings.getDisabledSystemPkgLPr(disabledPkgName) != null) {
+ // The updated-package data for /system apk remains inconsistently
+ // after the package data for /data apk is lost accidentally.
+ // To recover it, enable /system apk and install it as non-updated system app.
+ Slog.w(TAG, "Inconsistent package setting of updated system app for "
+ + disabledPkgName + ". To recover it, enable the system app"
+ + "and install it as non-updated system app.");
+ mSettings.removeDisabledSystemPackageLPw(disabledPkgName);
+ }
disabledPkgSetting = mSettings.getDisabledSystemPkgLPr(disabledPkgName);
isSystemPkgUpdated = disabledPkgSetting != null;
@@ -17790,17 +17816,6 @@
}
}
- static boolean locationIsPrivileged(String path) {
- // TODO(dariofreni): include APEX partitions when they will support priv apps.
- for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) {
- SystemPartition partition = SYSTEM_PARTITIONS.get(i);
- if (partition.containsPrivPath(path)) {
- return true;
- }
- }
- return false;
- }
-
private static @Nullable SystemPartition resolveApexToSystemPartition(
ApexManager.ActiveApexInfo apexInfo) {
for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) {
@@ -17808,7 +17823,7 @@
if (apexInfo.preinstalledApexPath.getAbsolutePath().startsWith(
sp.folder.getAbsolutePath())) {
return new SystemPartition(apexInfo.apexDirectory, sp.scanFlag,
- false /* hasPriv */, false /* hasOverlays */);
+ false /* hasOverlays */);
}
}
return null;
@@ -22241,8 +22256,9 @@
continue;
}
final String packageName = ps.pkg.packageName;
- // Skip over if system app
- if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ // Skip over if system app or static shared library
+ if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0
+ || !TextUtils.isEmpty(ps.pkg.staticSharedLibName)) {
continue;
}
if (DEBUG_CLEAN_APKS) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index a11ae8c..66c77f5 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3513,7 +3513,7 @@
int pkgFlags = 0;
int pkgPrivateFlags = 0;
pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
- if (PackageManagerService.locationIsPrivileged(codePathStr)) {
+ if (codePathStr.contains("/priv-app/")) {
pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
}
PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr),
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 8253b392..f0a1c70 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -495,7 +495,7 @@
final private IUidObserver mUidObserver = new IUidObserver.Stub() {
@Override
- public void onUidStateChanged(int uid, int procState, long procStateSeq) {
+ public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) {
injectPostToHandler(() -> handleOnUidStateChanged(uid, procState));
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index a2aeaf1..5c9b9c9 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1593,6 +1593,7 @@
/** @return a specific user restriction that's in effect currently. */
@Override
public boolean hasUserRestriction(String restrictionKey, @UserIdInt int userId) {
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "hasUserRestriction");
return mLocalService.hasUserRestriction(restrictionKey, userId);
}
@@ -1717,6 +1718,7 @@
*/
@Override
public Bundle getUserRestrictions(@UserIdInt int userId) {
+ checkManageOrInteractPermIfCallerInOtherProfileGroup(userId, "getUserRestrictions");
return UserRestrictionsUtils.clone(getEffectiveUserRestrictions(userId));
}
@@ -4000,9 +4002,14 @@
long now = System.currentTimeMillis();
final long nowRealtime = SystemClock.elapsedRealtime();
- final int currentUser = LocalServices.getService(ActivityManagerInternal.class)
- .getCurrentUserId();
- pw.print("Current user: "); pw.println(currentUser);
+ final ActivityManagerInternal amInternal = LocalServices
+ .getService(ActivityManagerInternal.class);
+ pw.print("Current user: ");
+ if (amInternal != null) {
+ pw.println(amInternal.getCurrentUserId());
+ } else {
+ pw.println("N/A");
+ }
StringBuilder sb = new StringBuilder();
synchronized (mPackagesLock) {
diff --git a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
index 323c957..ef6b24c 100644
--- a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
+++ b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
@@ -49,13 +49,14 @@
* <p>If {@link #isEnforceMode()} is false, then all system packages are always installed for all
* users. The following applies when it is true.
*
- * Any package can be in one of three states in the SystemConfig whitelist
+ * <p>Any package can be in one of three states in the {@code SystemConfig} whitelist
* <ol>
* <li>Explicitly blacklisted for a particular user type</li>
* <li>Explicitly whitelisted for a particular user type</li>
* <li>Not mentioned at all, for any user type (neither whitelisted nor blacklisted)</li>
* </ol>
- * Blacklisting always takes precedence - if a package is blacklisted for a particular user,
+ *
+ * <p>Blacklisting always takes precedence - if a package is blacklisted for a particular user,
* it won't be installed on that type of user (even if it is also whitelisted for that user).
* Next comes whitelisting - if it is whitelisted for a particular user, it will be installed on
* that type of user (as long as it isn't blacklisted).
@@ -69,6 +70,12 @@
* <li>Either way, for {@link UserHandle#USER_SYSTEM}, the package will be implicitly
* whitelisted so that it can be used for local development purposes.</li>
* </ul>
+ *
+ * <p><b>NOTE:</b> the {@code SystemConfig} state is only updated on first boot or after a system
+ * update. So, to verify changes during development, you can emulate the latter by calling:
+ * <pre><code>
+ * adb shell setprop persist.pm.mock-upgrade true
+ * </code></pre>
*/
class UserSystemPackageInstaller {
private static final String TAG = "UserManagerService";
@@ -109,13 +116,13 @@
* <p>Packages that are whitelisted, but then blacklisted so that they aren't to be installed on
* any user, are purposefully still present in this list.
*/
- private final ArrayMap<String, Integer> mWhitelitsedPackagesForUserTypes;
+ private final ArrayMap<String, Integer> mWhitelistedPackagesForUserTypes;
private final UserManagerService mUm;
UserSystemPackageInstaller(UserManagerService ums) {
mUm = ums;
- mWhitelitsedPackagesForUserTypes =
+ mWhitelistedPackagesForUserTypes =
determineWhitelistedPackagesForUserTypes(SystemConfig.getInstance());
}
@@ -123,7 +130,7 @@
@VisibleForTesting
UserSystemPackageInstaller(UserManagerService ums, ArrayMap<String, Integer> whitelist) {
mUm = ums;
- mWhitelitsedPackagesForUserTypes = whitelist;
+ mWhitelistedPackagesForUserTypes = whitelist;
}
/**
@@ -242,7 +249,7 @@
return (whitelistMode & USER_TYPE_PACKAGE_WHITELIST_MODE_IMPLICIT_WHITELIST) != 0;
}
- /** Gets the PackageWhitelistMode for use of {@link #mWhitelitsedPackagesForUserTypes}. */
+ /** Gets the PackageWhitelistMode for use of {@link #mWhitelistedPackagesForUserTypes}. */
private @PackageWhitelistMode int getWhitelistMode() {
final int runtimeMode = SystemProperties.getInt(
PACKAGE_WHITELIST_MODE_PROP, USER_TYPE_PACKAGE_WHITELIST_MODE_DEVICE_DEFAULT);
@@ -283,7 +290,7 @@
if (!pkg.isSystem()) {
return;
}
- if (shouldInstallPackage(pkg, mWhitelitsedPackagesForUserTypes,
+ if (shouldInstallPackage(pkg, mWhitelistedPackagesForUserTypes,
whitelistedPackages, isImplicitWhitelistMode, isSystemUser)) {
// Although the whitelist uses manifest names, this function returns packageNames.
installPackages.add(pkg.packageName);
@@ -333,10 +340,10 @@
*/
@VisibleForTesting
@NonNull Set<String> getWhitelistedPackagesForUserType(int flags) {
- Set<String> installablePkgs = new ArraySet<>(mWhitelitsedPackagesForUserTypes.size());
- for (int i = 0; i < mWhitelitsedPackagesForUserTypes.size(); i++) {
- String pkgName = mWhitelitsedPackagesForUserTypes.keyAt(i);
- int whitelistedUserTypes = mWhitelitsedPackagesForUserTypes.valueAt(i);
+ Set<String> installablePkgs = new ArraySet<>(mWhitelistedPackagesForUserTypes.size());
+ for (int i = 0; i < mWhitelistedPackagesForUserTypes.size(); i++) {
+ String pkgName = mWhitelistedPackagesForUserTypes.keyAt(i);
+ int whitelistedUserTypes = mWhitelistedPackagesForUserTypes.valueAt(i);
if ((flags & whitelistedUserTypes) != 0) {
installablePkgs.add(pkgName);
}
@@ -353,7 +360,7 @@
* completely blacklists an AOSP app).
*/
private Set<String> getWhitelistedSystemPackages() {
- return mWhitelitsedPackagesForUserTypes.keySet();
+ return mWhitelistedPackagesForUserTypes.keySet();
}
/**
@@ -449,18 +456,28 @@
}
void dump(PrintWriter pw) {
- pw.print("Whitelisted packages per user type");
- final int size = mWhitelitsedPackagesForUserTypes.size();
+ final String prefix = " ";
+ final int mode = getWhitelistMode();
+ pw.println("Whitelisted packages per user type");
+ pw.print(prefix); pw.print("Mode: ");
+ pw.print(mode);
+ pw.print(isEnforceMode(mode) ? " (enforced)" : "");
+ pw.print(isLogMode(mode) ? " (logged)" : "");
+ pw.print(isImplicitWhitelistMode(mode) ? " (implicit)" : "");
+ pw.println();
+
+ final int size = mWhitelistedPackagesForUserTypes.size();
if (size == 0) {
- pw.println(": N/A");
+ pw.print(prefix); pw.println("No packages");
return;
}
- pw.println(" (" + size + " packages)");
+ final String prefix2 = prefix + prefix;
+ pw.print(prefix); pw.print(size); pw.println(" packages:");
for (int i = 0; i < size; i++) {
- final String pkgName = mWhitelitsedPackagesForUserTypes.keyAt(i);
+ final String pkgName = mWhitelistedPackagesForUserTypes.keyAt(i);
final String whitelistedUserTypes =
- UserInfo.flagsToString(mWhitelitsedPackagesForUserTypes.valueAt(i));
- pw.println(" " + pkgName + ": " + whitelistedUserTypes);
+ UserInfo.flagsToString(mWhitelistedPackagesForUserTypes.valueAt(i));
+ pw.print(prefix2); pw.print(pkgName); pw.print(": "); pw.println(whitelistedUserTypes);
}
}
}
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index f56231f..41dcaa5 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -16,8 +16,6 @@
package com.android.server.pm.dex;
-import static android.provider.DeviceConfig.NAMESPACE_DEX_BOOT;
-
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.dex.PackageDexUsage.DexUseInfo;
import static com.android.server.pm.dex.PackageDexUsage.PackageUseInfo;
@@ -31,7 +29,6 @@
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.storage.StorageManager;
-import android.provider.DeviceConfig;
import android.util.Log;
import android.util.Slog;
import android.util.jar.StrictJarFile;
@@ -72,10 +69,6 @@
private static final String PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB_LIST =
"pm.dexopt.priv-apps-oob-list";
- // flags for Device Config API
- private static final String PRIV_APPS_OOB_ENABLED = "priv_apps_oob_enabled";
- private static final String PRIV_APPS_OOB_WHITELIST = "priv_apps_oob_whitelist";
-
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final Context mContext;
@@ -717,24 +710,16 @@
return isPackageSelectedToRunOobInternal(
SystemProperties.getBoolean(PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB, false),
SystemProperties.get(PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB_LIST, "ALL"),
- DeviceConfig.getProperty(NAMESPACE_DEX_BOOT, PRIV_APPS_OOB_ENABLED),
- DeviceConfig.getProperty(NAMESPACE_DEX_BOOT, PRIV_APPS_OOB_WHITELIST),
packageNamesInSameProcess);
}
@VisibleForTesting
- /* package */ static boolean isPackageSelectedToRunOobInternal(
- boolean isDefaultEnabled, String defaultWhitelist, String overrideEnabled,
- String overrideWhitelist, Collection<String> packageNamesInSameProcess) {
- // Allow experiment (if exists) to override device configuration.
- boolean enabled = overrideEnabled != null ? overrideEnabled.equals("true")
- : isDefaultEnabled;
- if (!enabled) {
+ /* package */ static boolean isPackageSelectedToRunOobInternal(boolean isEnabled,
+ String whitelist, Collection<String> packageNamesInSameProcess) {
+ if (!isEnabled) {
return false;
}
- // Similarly, experiment flag can override the whitelist.
- String whitelist = overrideWhitelist != null ? overrideWhitelist : defaultWhitelist;
if ("ALL".equals(whitelist)) {
return true;
}
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index ef4c12e..198bb14 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -53,6 +53,7 @@
import android.util.SparseBooleanArray;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.LocalServices;
import com.android.server.Watchdog;
@@ -469,44 +470,39 @@
List<Rollback> restoreInProgress = new ArrayList<>();
Set<String> apexPackageNames = new HashSet<>();
synchronized (mLock) {
- for (Rollback rollback : mRollbacks) {
- if (rollback.isStaged()) {
+ Iterator<Rollback> iter = mRollbacks.iterator();
+ while (iter.hasNext()) {
+ Rollback rollback = iter.next();
+ if (!rollback.isStaged()) {
+ // We only care about staged rollbacks here
+ continue;
+ }
+
+ PackageInstaller.SessionInfo session = mContext.getPackageManager()
+ .getPackageInstaller().getSessionInfo(rollback.getStagedSessionId());
+ if (session == null || session.isStagedSessionFailed()) {
+ iter.remove();
+ rollback.delete(mAppDataRollbackHelper);
+ continue;
+ }
+
+ if (session.isStagedSessionApplied()) {
if (rollback.isEnabling()) {
enabling.add(rollback);
} else if (rollback.isRestoreUserDataInProgress()) {
restoreInProgress.add(rollback);
}
-
- apexPackageNames.addAll(rollback.getApexPackageNames());
}
+ apexPackageNames.addAll(rollback.getApexPackageNames());
}
}
for (Rollback rollback : enabling) {
- PackageInstaller installer = mContext.getPackageManager().getPackageInstaller();
- PackageInstaller.SessionInfo session =
- installer.getSessionInfo(rollback.getStagedSessionId());
- if (session == null || session.isStagedSessionFailed()) {
- // TODO: Do we need to remove this from
- // mRollbacks, or is it okay to leave as
- // unavailable until the next reboot when it will go
- // away on its own?
- rollback.delete(mAppDataRollbackHelper);
- } else if (session.isStagedSessionApplied()) {
- makeRollbackAvailable(rollback);
- }
+ makeRollbackAvailable(rollback);
}
for (Rollback rollback : restoreInProgress) {
- PackageInstaller installer = mContext.getPackageManager().getPackageInstaller();
- PackageInstaller.SessionInfo session =
- installer.getSessionInfo(rollback.getStagedSessionId());
- // TODO: What if session is null?
- if (session != null) {
- if (session.isStagedSessionApplied() || session.isStagedSessionFailed()) {
- rollback.setRestoreUserDataInProgress(false);
- }
- }
+ rollback.setRestoreUserDataInProgress(false);
}
for (String apexPackageName : apexPackageNames) {
@@ -1133,6 +1129,8 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
synchronized (mLock) {
for (Rollback rollback : mRollbacks) {
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index ec64ee6..b6934c9 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -16,7 +16,6 @@
package com.android.server.statusbar;
-import android.graphics.Rect;
import android.os.Bundle;
import android.view.InsetsState.InternalInsetType;
import android.view.WindowInsetsController.Appearance;
@@ -79,9 +78,7 @@
void startAssist(Bundle args);
void onCameraLaunchGestureDetected(int source);
void topAppWindowChanged(int displayId, boolean isFullscreen, boolean isImmersive);
- void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis, int dockedStackVis,
- int mask, Rect fullscreenBounds, Rect dockedBounds, boolean isNavbarColorManagedByIme,
- String cause);
+ void setDisableFlags(int displayId, int flags, String cause);
void toggleSplitScreen();
void appTransitionFinished(int displayId);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 489c343..25c41f5 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -25,7 +25,6 @@
import android.app.StatusBarManager;
import android.content.ComponentName;
import android.content.Context;
-import android.graphics.Rect;
import android.hardware.biometrics.IBiometricServiceReceiverInternal;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
@@ -43,10 +42,11 @@
import android.service.notification.NotificationStats;
import android.text.TextUtils;
import android.util.ArrayMap;
-import android.util.Log;
+import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.InsetsState.InternalInsetType;
import android.view.WindowInsetsController.Appearance;
import com.android.internal.R;
@@ -263,12 +263,8 @@
}
@Override
- public void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenBounds, Rect dockedBounds,
- boolean isNavbarColorManagedByIme, String cause) {
- StatusBarManagerService.this.setSystemUiVisibility(displayId, vis, fullscreenStackVis,
- dockedStackVis, mask, fullscreenBounds, dockedBounds, isNavbarColorManagedByIme,
- cause);
+ public void setDisableFlags(int displayId, int flags, String cause) {
+ StatusBarManagerService.this.setDisableFlags(displayId, flags, cause);
}
@Override
@@ -473,7 +469,10 @@
@Override
public void onSystemBarAppearanceChanged(int displayId, @Appearance int appearance,
AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
- // TODO (b/118118435): save the information to UiState
+ final UiState state = getUiState(displayId);
+ if (!state.appearanceEquals(appearance, appearanceRegions, navbarColorManagedByIme)) {
+ state.setAppearance(appearance, appearanceRegions, navbarColorManagedByIme);
+ }
if (mBar != null) {
try {
mBar.onSystemBarAppearanceChanged(displayId, appearance, appearanceRegions,
@@ -483,7 +482,8 @@
}
@Override
- public void showTransient(int displayId, int[] types) {
+ public void showTransient(int displayId, @InternalInsetType int[] types) {
+ getUiState(displayId).showTransient(types);
if (mBar != null) {
try {
mBar.showTransient(displayId, types);
@@ -492,7 +492,8 @@
}
@Override
- public void abortTransient(int displayId, int[] types) {
+ public void abortTransient(int displayId, @InternalInsetType int[] types) {
+ getUiState(displayId).clearTransient(types);
if (mBar != null) {
try {
mBar.abortTransient(displayId, types);
@@ -896,54 +897,20 @@
}
}
- @Override
- public void setSystemUiVisibility(int displayId, int vis, int mask, String cause) {
- final UiState state = getUiState(displayId);
- setSystemUiVisibility(displayId, vis, 0, 0, mask,
- state.mFullscreenStackBounds, state.mDockedStackBounds,
- state.mNavbarColorManagedByIme, cause);
- }
-
- private void setSystemUiVisibility(int displayId, int vis, int fullscreenStackVis,
- int dockedStackVis, int mask, Rect fullscreenBounds, Rect dockedBounds,
- boolean isNavbarColorManagedByIme, String cause) {
+ private void setDisableFlags(int displayId, int flags, String cause) {
// also allows calls from window manager which is in this process.
enforceStatusBarService();
- if (SPEW) Slog.d(TAG, "setSystemUiVisibility(0x" + Integer.toHexString(vis) + ")");
+ final int unknownFlags = flags & ~StatusBarManager.DISABLE_MASK;
+ if (unknownFlags != 0) {
+ Slog.e(TAG, "Unknown disable flags: 0x" + Integer.toHexString(unknownFlags),
+ new RuntimeException());
+ }
+
+ if (SPEW) Slog.d(TAG, "setDisableFlags(0x" + Integer.toHexString(flags) + ")");
synchronized (mLock) {
- updateUiVisibilityLocked(displayId, vis, fullscreenStackVis, dockedStackVis, mask,
- fullscreenBounds, dockedBounds, isNavbarColorManagedByIme);
- disableLocked(
- displayId,
- mCurrentUserId,
- vis & StatusBarManager.DISABLE_MASK,
- mSysUiVisToken,
- cause, 1);
- }
- }
-
- private void updateUiVisibilityLocked(final int displayId, final int vis,
- final int fullscreenStackVis, final int dockedStackVis, final int mask,
- final Rect fullscreenBounds, final Rect dockedBounds,
- final boolean isNavbarColorManagedByIme) {
- final UiState state = getUiState(displayId);
- if (!state.systemUiStateEquals(vis, fullscreenStackVis, dockedStackVis,
- fullscreenBounds, dockedBounds, isNavbarColorManagedByIme)) {
- state.setSystemUiState(vis, fullscreenStackVis, dockedStackVis, fullscreenBounds,
- dockedBounds, isNavbarColorManagedByIme);
- mHandler.post(() -> {
- if (mBar != null) {
- try {
- mBar.setSystemUiVisibility(displayId, vis, fullscreenStackVis,
- dockedStackVis, mask, fullscreenBounds, dockedBounds,
- isNavbarColorManagedByIme);
- } catch (RemoteException ex) {
- Log.w(TAG, "Can not get StatusBar!");
- }
- }
- });
+ disableLocked(displayId, mCurrentUserId, flags, mSysUiVisToken, cause, 1);
}
}
@@ -965,11 +932,10 @@
}
private class UiState {
- private int mSystemUiVisibility = 0;
- private int mFullscreenStackSysUiVisibility = 0;
- private int mDockedStackSysUiVisibility = 0;
- private final Rect mFullscreenStackBounds = new Rect();
- private final Rect mDockedStackBounds = new Rect();
+ private @Appearance int mAppearance = 0;
+ private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0];
+ private ArraySet<Integer> mTransientBarTypes = new ArraySet<>();
+ private boolean mNavbarColorManagedByIme = false;
private boolean mFullscreen = false;
private boolean mImmersive = false;
private int mDisabled1 = 0;
@@ -978,7 +944,47 @@
private int mImeBackDisposition = 0;
private boolean mShowImeSwitcher = false;
private IBinder mImeToken = null;
- private boolean mNavbarColorManagedByIme = false;
+
+ private void setAppearance(@Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
+ mAppearance = appearance;
+ mAppearanceRegions = appearanceRegions;
+ mNavbarColorManagedByIme = navbarColorManagedByIme;
+ }
+
+ private boolean appearanceEquals(@Appearance int appearance,
+ AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme) {
+ if (mAppearance != appearance || mAppearanceRegions.length != appearanceRegions.length
+ || mNavbarColorManagedByIme != navbarColorManagedByIme) {
+ return false;
+ }
+ for (int i = appearanceRegions.length - 1; i >= 0; i--) {
+ if (!mAppearanceRegions[i].equals(appearanceRegions[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void showTransient(@InternalInsetType int[] types) {
+ for (int type : types) {
+ mTransientBarTypes.add(type);
+ }
+ }
+
+ private void clearTransient(@InternalInsetType int[] types) {
+ for (int type : types) {
+ mTransientBarTypes.remove(type);
+ }
+ }
+
+ private void setFullscreen(boolean isFullscreen) {
+ mFullscreen = isFullscreen;
+ }
+
+ private void setImmersive(boolean isImmersive) {
+ mImmersive = isImmersive;
+ }
private int getDisabled1() {
return mDisabled1;
@@ -993,40 +999,10 @@
mDisabled2 = disabled2;
}
- private void setFullscreen(boolean isFullscreen) {
- mFullscreen = isFullscreen;
- }
-
- private void setImmersive(boolean immersive) {
- mImmersive = immersive;
- }
-
private boolean disableEquals(int disabled1, int disabled2) {
return mDisabled1 == disabled1 && mDisabled2 == disabled2;
}
- private void setSystemUiState(final int vis, final int fullscreenStackVis,
- final int dockedStackVis, final Rect fullscreenBounds, final Rect dockedBounds,
- final boolean navbarColorManagedByIme) {
- mSystemUiVisibility = vis;
- mFullscreenStackSysUiVisibility = fullscreenStackVis;
- mDockedStackSysUiVisibility = dockedStackVis;
- mFullscreenStackBounds.set(fullscreenBounds);
- mDockedStackBounds.set(dockedBounds);
- mNavbarColorManagedByIme = navbarColorManagedByIme;
- }
-
- private boolean systemUiStateEquals(final int vis, final int fullscreenStackVis,
- final int dockedStackVis, final Rect fullscreenBounds, final Rect dockedBounds,
- final boolean navbarColorManagedByIme) {
- return mSystemUiVisibility == vis
- && mFullscreenStackSysUiVisibility == fullscreenStackVis
- && mDockedStackSysUiVisibility == dockedStackVis
- && mFullscreenStackBounds.equals(fullscreenBounds)
- && mDockedStackBounds.equals(dockedBounds)
- && mNavbarColorManagedByIme == navbarColorManagedByIme;
- }
-
private void setImeWindowState(final int vis, final int backDisposition,
final boolean showImeSwitcher, final IBinder token) {
mImeWindowVis = vis;
@@ -1084,13 +1060,16 @@
// TODO(b/118592525): Currently, status bar only works on the default display.
// Make it aware of multi-display if needed.
final UiState state = mDisplayUiState.get(DEFAULT_DISPLAY);
+ final int[] transientBarTypes = new int[state.mTransientBarTypes.size()];
+ for (int i = 0; i < transientBarTypes.length; i++) {
+ transientBarTypes[i] = state.mTransientBarTypes.valueAt(i);
+ }
return new RegisterStatusBarResult(icons, gatherDisableActionsLocked(mCurrentUserId, 1),
- state.mSystemUiVisibility, state.mImeWindowVis,
+ state.mAppearance, state.mAppearanceRegions, state.mImeWindowVis,
state.mImeBackDisposition, state.mShowImeSwitcher,
- gatherDisableActionsLocked(mCurrentUserId, 2),
- state.mFullscreenStackSysUiVisibility, state.mDockedStackSysUiVisibility,
- state.mImeToken, state.mFullscreenStackBounds, state.mDockedStackBounds,
- state.mNavbarColorManagedByIme, state.mFullscreen, state.mImmersive);
+ gatherDisableActionsLocked(mCurrentUserId, 2), state.mImeToken,
+ state.mNavbarColorManagedByIme, state.mFullscreen, state.mImmersive,
+ transientBarTypes);
}
}
@@ -1364,12 +1343,26 @@
}
@Override
- public void grantInlineReplyUriPermission(String key, Uri uri) {
+ public void grantInlineReplyUriPermission(String key, Uri uri, UserHandle user,
+ String packageName) {
enforceStatusBarService();
int callingUid = Binder.getCallingUid();
long identity = Binder.clearCallingIdentity();
try {
- mNotificationDelegate.grantInlineReplyUriPermission(key, uri, callingUid);
+ mNotificationDelegate.grantInlineReplyUriPermission(key, uri, user, packageName,
+ callingUid);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void clearInlineReplyUriPermissions(String key) {
+ enforceStatusBarService();
+ int callingUid = Binder.getCallingUid();
+ long identity = Binder.clearCallingIdentity();
+ try {
+ mNotificationDelegate.clearInlineReplyUriPermissions(key, callingUid);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java b/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java
index 852f707..cb0b45c 100644
--- a/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/EmergencyNumberDbInstallReceiver.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.Intent;
+import android.telephony.TelephonyManager;
import android.util.Slog;
/**
@@ -34,6 +35,11 @@
@Override
protected void postInstall(Context context, Intent intent) {
Slog.i(TAG, "Emergency number database is updated in file partition");
- // TODO Send a notification to EmergencyNumberTracker for updating of emergency number db.
+
+ // Notify EmergencyNumberTracker for emergency number installation complete.
+ Intent notifyInstallComplete = new Intent(
+ TelephonyManager.ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED);
+ context.sendBroadcast(
+ notifyInstallComplete, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
}
}
diff --git a/services/core/java/com/android/server/wallpaper/GLHelper.java b/services/core/java/com/android/server/wallpaper/GLHelper.java
new file mode 100644
index 0000000..1d733f5
--- /dev/null
+++ b/services/core/java/com/android/server/wallpaper/GLHelper.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wallpaper;
+
+import static android.opengl.EGL14.EGL_ALPHA_SIZE;
+import static android.opengl.EGL14.EGL_BLUE_SIZE;
+import static android.opengl.EGL14.EGL_CONFIG_CAVEAT;
+import static android.opengl.EGL14.EGL_CONTEXT_CLIENT_VERSION;
+import static android.opengl.EGL14.EGL_DEFAULT_DISPLAY;
+import static android.opengl.EGL14.EGL_DEPTH_SIZE;
+import static android.opengl.EGL14.EGL_GREEN_SIZE;
+import static android.opengl.EGL14.EGL_HEIGHT;
+import static android.opengl.EGL14.EGL_NONE;
+import static android.opengl.EGL14.EGL_NO_CONTEXT;
+import static android.opengl.EGL14.EGL_NO_DISPLAY;
+import static android.opengl.EGL14.EGL_NO_SURFACE;
+import static android.opengl.EGL14.EGL_OPENGL_ES2_BIT;
+import static android.opengl.EGL14.EGL_RED_SIZE;
+import static android.opengl.EGL14.EGL_RENDERABLE_TYPE;
+import static android.opengl.EGL14.EGL_STENCIL_SIZE;
+import static android.opengl.EGL14.EGL_WIDTH;
+import static android.opengl.EGL14.eglChooseConfig;
+import static android.opengl.EGL14.eglCreateContext;
+import static android.opengl.EGL14.eglCreatePbufferSurface;
+import static android.opengl.EGL14.eglDestroyContext;
+import static android.opengl.EGL14.eglDestroySurface;
+import static android.opengl.EGL14.eglGetDisplay;
+import static android.opengl.EGL14.eglGetError;
+import static android.opengl.EGL14.eglInitialize;
+import static android.opengl.EGL14.eglMakeCurrent;
+import static android.opengl.EGL14.eglTerminate;
+import static android.opengl.GLES20.GL_MAX_TEXTURE_SIZE;
+import static android.opengl.GLES20.glGetIntegerv;
+
+import android.opengl.EGLConfig;
+import android.opengl.EGLContext;
+import android.opengl.EGLDisplay;
+import android.opengl.EGLSurface;
+import android.opengl.GLUtils;
+import android.os.SystemProperties;
+import android.util.Log;
+
+class GLHelper {
+ private static final String TAG = GLHelper.class.getSimpleName();
+ private static final int sMaxTextureSize;
+
+ static {
+ int maxTextureSize = SystemProperties.getInt("sys.max_texture_size", 0);
+ sMaxTextureSize = maxTextureSize > 0 ? maxTextureSize : retrieveTextureSizeFromGL();
+ }
+
+ private static int retrieveTextureSizeFromGL() {
+ try {
+ String err;
+
+ // Before we can retrieve info from GL,
+ // we have to create EGLContext, EGLConfig and EGLDisplay first.
+ // We will fail at querying info from GL once one of above failed.
+ // When this happens, we will use defValue instead.
+ EGLDisplay eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ if (eglDisplay == null || eglDisplay == EGL_NO_DISPLAY) {
+ err = "eglGetDisplay failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ }
+
+ if (!eglInitialize(eglDisplay, null, 0 /* majorOffset */, null, 1 /* minorOffset */)) {
+ err = "eglInitialize failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ }
+
+ EGLConfig eglConfig = null;
+ int[] configsCount = new int[1];
+ EGLConfig[] configs = new EGLConfig[1];
+ int[] configSpec = new int[] {
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 0,
+ EGL_DEPTH_SIZE, 0,
+ EGL_STENCIL_SIZE, 0,
+ EGL_CONFIG_CAVEAT, EGL_NONE,
+ EGL_NONE
+ };
+
+ if (!eglChooseConfig(eglDisplay, configSpec, 0 /* attrib_listOffset */,
+ configs, 0 /* configOffset */, 1 /* config_size */,
+ configsCount, 0 /* num_configOffset */)) {
+ err = "eglChooseConfig failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ } else if (configsCount[0] > 0) {
+ eglConfig = configs[0];
+ }
+
+ if (eglConfig == null) {
+ throw new RuntimeException("eglConfig not initialized!");
+ }
+
+ int[] attr_list = new int[] {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+ EGLContext eglContext = eglCreateContext(
+ eglDisplay, eglConfig, EGL_NO_CONTEXT, attr_list, 0 /* offset */);
+
+ if (eglContext == null || eglContext == EGL_NO_CONTEXT) {
+ err = "eglCreateContext failed: " + GLUtils.getEGLErrorString(eglGetError());
+ throw new RuntimeException(err);
+ }
+
+ // We create a push buffer temporarily for querying info from GL.
+ int[] attrs = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
+ EGLSurface eglSurface =
+ eglCreatePbufferSurface(eglDisplay, eglConfig, attrs, 0 /* offset */);
+ eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
+
+ // Now, we are ready to query the info from GL.
+ int[] maxSize = new int[1];
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxSize, 0 /* offset */);
+
+ // We have got the info we want, release all egl resources.
+ eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglDestroySurface(eglDisplay, eglSurface);
+ eglDestroyContext(eglDisplay, eglContext);
+ eglTerminate(eglDisplay);
+ return maxSize[0];
+ } catch (RuntimeException e) {
+ Log.w(TAG, "Retrieve from GL failed", e);
+ return Integer.MAX_VALUE;
+ }
+ }
+
+ static int getMaxTextureSize() {
+ return sMaxTextureSize;
+ }
+}
+
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 3663f46..3cc6428 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -134,6 +134,9 @@
private static final boolean DEBUG = false;
private static final boolean DEBUG_LIVE = true;
+ // This 100MB limitation is defined in RecordingCanvas.
+ private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024;
+
public static class Lifecycle extends SystemService {
private IWallpaperManagerService mService;
@@ -572,7 +575,9 @@
// Only generate crop for default display.
final DisplayData wpData = getDisplayDataOrCreate(DEFAULT_DISPLAY);
- Rect cropHint = new Rect(wallpaper.cropHint);
+ final Rect cropHint = new Rect(wallpaper.cropHint);
+ final DisplayInfo displayInfo = new DisplayInfo();
+ mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
if (DEBUG) {
Slog.v(TAG, "Generating crop for new wallpaper(s): 0x"
@@ -618,12 +623,12 @@
}
// scale if the crop height winds up not matching the recommended metrics
- needScale = (wpData.mHeight != cropHint.height());
+ needScale = wpData.mHeight != cropHint.height()
+ || cropHint.height() > GLHelper.getMaxTextureSize()
+ || cropHint.width() > GLHelper.getMaxTextureSize();
//make sure screen aspect ratio is preserved if width is scaled under screen size
if (needScale) {
- final DisplayInfo displayInfo = new DisplayInfo();
- mDisplayManager.getDisplay(DEFAULT_DISPLAY).getDisplayInfo(displayInfo);
final float scaleByHeight = (float) wpData.mHeight / (float) cropHint.height();
final int newWidth = (int) (cropHint.width() * scaleByHeight);
if (newWidth < displayInfo.logicalWidth) {
@@ -644,14 +649,29 @@
if (!needCrop && !needScale) {
// Simple case: the nominal crop fits what we want, so we take
// the whole thing and just copy the image file directly.
- if (DEBUG) {
- Slog.v(TAG, "Null crop of new wallpaper; copying");
+
+ // TODO: It is not accurate to estimate bitmap size without decoding it,
+ // may be we can try to remove this optimized way in the future,
+ // that means, we will always go into the 'else' block.
+
+ // This is just a quick estimation, may be smaller than it is.
+ long estimateSize = options.outWidth * options.outHeight * 4;
+
+ // A bitmap over than MAX_BITMAP_SIZE will make drawBitmap() fail.
+ // Please see: RecordingCanvas#throwIfCannotDraw.
+ if (estimateSize < MAX_BITMAP_SIZE) {
+ success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
}
- success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
+
if (!success) {
wallpaper.cropFile.delete();
// TODO: fall back to default wallpaper in this case
}
+
+ if (DEBUG) {
+ Slog.v(TAG, "Null crop of new wallpaper, estimate size="
+ + estimateSize + ", success=" + success);
+ }
} else {
// Fancy case: crop and scale. First, we decode and scale down if appropriate.
FileOutputStream f = null;
@@ -665,49 +685,78 @@
// We calculate the largest power-of-two under the actual ratio rather than
// just let the decode take care of it because we also want to remap where the
// cropHint rectangle lies in the decoded [super]rect.
- final BitmapFactory.Options scaler;
final int actualScale = cropHint.height() / wpData.mHeight;
int scale = 1;
- while (2*scale < actualScale) {
+ while (2 * scale <= actualScale) {
scale *= 2;
}
- if (scale > 1) {
- scaler = new BitmapFactory.Options();
- scaler.inSampleSize = scale;
+ options.inSampleSize = scale;
+ options.inJustDecodeBounds = false;
+
+ final Rect estimateCrop = new Rect(cropHint);
+ estimateCrop.scale(1f / options.inSampleSize);
+ final float hRatio = (float) wpData.mHeight / estimateCrop.height();
+ final int destHeight = (int) (estimateCrop.height() * hRatio);
+ final int destWidth = (int) (estimateCrop.width() * hRatio);
+
+ // We estimated an invalid crop, try to adjust the cropHint to get a valid one.
+ if (destWidth > GLHelper.getMaxTextureSize()) {
+ int newHeight = (int) (wpData.mHeight / hRatio);
+ int newWidth = (int) (wpData.mWidth / hRatio);
+
if (DEBUG) {
- Slog.v(TAG, "Downsampling cropped rect with scale " + scale);
+ Slog.v(TAG, "Invalid crop dimensions, trying to adjust.");
}
- } else {
- scaler = null;
+
+ estimateCrop.set(cropHint);
+ estimateCrop.left += (cropHint.width() - newWidth) / 2;
+ estimateCrop.top += (cropHint.height() - newHeight) / 2;
+ estimateCrop.right = estimateCrop.left + newWidth;
+ estimateCrop.bottom = estimateCrop.top + newHeight;
+ cropHint.set(estimateCrop);
+ estimateCrop.scale(1f / options.inSampleSize);
}
- Bitmap cropped = decoder.decodeRegion(cropHint, scaler);
+
+ // We've got the safe cropHint; now we want to scale it properly to
+ // the desired rectangle.
+ // That's a height-biased operation: make it fit the hinted height.
+ final int safeHeight = (int) (estimateCrop.height() * hRatio);
+ final int safeWidth = (int) (estimateCrop.width() * hRatio);
+
+ if (DEBUG) {
+ Slog.v(TAG, "Decode parameters:");
+ Slog.v(TAG, " cropHint=" + cropHint + ", estimateCrop=" + estimateCrop);
+ Slog.v(TAG, " down sampling=" + options.inSampleSize
+ + ", hRatio=" + hRatio);
+ Slog.v(TAG, " dest=" + destWidth + "x" + destHeight);
+ Slog.v(TAG, " safe=" + safeWidth + "x" + safeHeight);
+ Slog.v(TAG, " maxTextureSize=" + GLHelper.getMaxTextureSize());
+ }
+
+ Bitmap cropped = decoder.decodeRegion(cropHint, options);
decoder.recycle();
if (cropped == null) {
Slog.e(TAG, "Could not decode new wallpaper");
} else {
- // We've got the extracted crop; now we want to scale it properly to
- // the desired rectangle. That's a height-biased operation: make it
- // fit the hinted height, and accept whatever width we end up with.
- cropHint.offsetTo(0, 0);
- cropHint.right /= scale; // adjust by downsampling factor
- cropHint.bottom /= scale;
- final float heightR =
- ((float) wpData.mHeight) / ((float) cropHint.height());
- if (DEBUG) {
- Slog.v(TAG, "scale " + heightR + ", extracting " + cropHint);
- }
- final int destWidth = (int)(cropHint.width() * heightR);
+ // We are safe to create final crop with safe dimensions now.
final Bitmap finalCrop = Bitmap.createScaledBitmap(cropped,
- destWidth, wpData.mHeight, true);
+ safeWidth, safeHeight, true);
if (DEBUG) {
Slog.v(TAG, "Final extract:");
Slog.v(TAG, " dims: w=" + wpData.mWidth
+ " h=" + wpData.mHeight);
- Slog.v(TAG, " out: w=" + finalCrop.getWidth()
+ Slog.v(TAG, " out: w=" + finalCrop.getWidth()
+ " h=" + finalCrop.getHeight());
}
+ // A bitmap over than MAX_BITMAP_SIZE will make drawBitmap() fail.
+ // Please see: RecordingCanvas#throwIfCannotDraw.
+ if (finalCrop.getByteCount() > MAX_BITMAP_SIZE) {
+ throw new RuntimeException(
+ "Too large bitmap, limit=" + MAX_BITMAP_SIZE);
+ }
+
f = new FileOutputStream(wallpaper.cropFile);
bos = new BufferedOutputStream(f, 32*1024);
finalCrop.compress(Bitmap.CompressFormat.JPEG, 100, bos);
@@ -1997,6 +2046,11 @@
if (!isWallpaperSupported(callingPackage)) {
return;
}
+
+ // Make sure both width and height are not larger than max texture size.
+ width = Math.min(width, GLHelper.getMaxTextureSize());
+ height = Math.min(height, GLHelper.getMaxTextureSize());
+
synchronized (mLock) {
int userId = UserHandle.getCallingUserId();
WallpaperData wallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 5e4f75c..c57ac11 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -132,17 +132,20 @@
return false;
}
- if (mWindowsForAccessibilityObserver.get(displayId) != null) {
- final Display display = dc.getDisplay();
- if (display.getType() == Display.TYPE_VIRTUAL && dc.getParentWindow() != null) {
- // The window observer of this embedded display had been set from
- // window manager after setting its parent window.
- return false;
- } else {
- throw new IllegalStateException(
- "Windows for accessibility callback of display "
- + displayId + " already set!");
+ final Display display = dc.getDisplay();
+ if (display.getType() == Display.TYPE_VIRTUAL && dc.getParentWindow() != null) {
+ // If this display is an embedded one, its window observer should have been set from
+ // window manager after setting its parent window. But if its window observer is
+ // empty, that means this mapping didn't be set, and needs to do this again.
+ // This happened when accessibility window observer is disabled and enabled again.
+ if (mWindowsForAccessibilityObserver.get(displayId) == null) {
+ handleWindowObserverOfEmbeddedDisplayLocked(displayId, dc.getParentWindow());
}
+ return false;
+ } else if (mWindowsForAccessibilityObserver.get(displayId) != null) {
+ throw new IllegalStateException(
+ "Windows for accessibility callback of display "
+ + displayId + " already set!");
}
mWindowsForAccessibilityObserver.put(displayId,
new WindowsForAccessibilityObserver(mService, displayId, callback));
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index 48a7b73..1268113 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -41,7 +41,6 @@
import static com.android.server.am.ActivityDisplayProto.SINGLE_TASK_INSTANCE;
import static com.android.server.am.ActivityDisplayProto.STACKS;
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
@@ -1523,7 +1522,7 @@
final ActivityStack stack = getChildAt(i);
final ArrayList<TaskRecord> tasks = stack.getAllTasks();
for (int j = tasks.size() - 1; j >= 0; --j) {
- stack.removeTask(tasks.get(j), "removeAllTasks", REMOVE_TASK_MODE_DESTROYING);
+ stack.removeChild(tasks.get(j), "removeAllTasks");
}
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
index 9d41d97..ff2c671 100644
--- a/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/wm/ActivityMetricsLogger.java
@@ -403,8 +403,7 @@
if (launchedActivity != null && launchedActivity.mDrawn) {
// Launched activity is already visible. We cannot measure windows drawn delay.
- reset(true /* abort */, info, "launched activity already visible",
- 0L /* timestampNs */);
+ abort(info, "launched activity already visible");
return;
}
@@ -422,8 +421,7 @@
if ((!isLoggableResultCode(resultCode) || launchedActivity == null || !processSwitch
|| windowingMode == WINDOWING_MODE_UNDEFINED) && !otherWindowModesLaunching) {
// Failed to launch or it was not a process switch, so we don't care about the timing.
- reset(true /* abort */, info, "failed to launch or not a process switch",
- 0L /* timestampNs */);
+ abort(info, "failed to launch or not a process switch");
return;
} else if (otherWindowModesLaunching) {
// Don't log this windowing mode but continue with the other windowing modes.
@@ -469,8 +467,7 @@
final WindowingModeTransitionInfoSnapshot infoSnapshot =
new WindowingModeTransitionInfoSnapshot(info);
if (allWindowsDrawn() && mLoggedTransitionStarting) {
- reset(false /* abort */, info, "notifyWindowsDrawn - all windows drawn",
- timestampNs /* timestampNs */);
+ reset(false /* abort */, info, "notifyWindowsDrawn - all windows drawn", timestampNs);
}
return infoSnapshot;
}
@@ -478,13 +475,13 @@
/**
* Notifies the tracker that the starting window was drawn.
*/
- void notifyStartingWindowDrawn(@WindowingMode int windowingMode, long timestamp) {
+ void notifyStartingWindowDrawn(@WindowingMode int windowingMode, long timestampNs) {
final WindowingModeTransitionInfo info = mWindowingModeTransitionInfo.get(windowingMode);
if (info == null || info.loggedStartingWindowDrawn) {
return;
}
info.loggedStartingWindowDrawn = true;
- info.startingWindowDelayMs = calculateDelay(timestamp);
+ info.startingWindowDelayMs = calculateDelay(timestampNs);
}
/**
@@ -544,10 +541,11 @@
mHandler.obtainMessage(MSG_CHECK_VISIBILITY, args).sendToTarget();
}
- private boolean hasVisibleNonFinishingActivity(TaskRecord t) {
+ /** @return {@code true} if the given task has an activity will be drawn. */
+ private static boolean hasActivityToBeDrawn(TaskRecord t) {
for (int i = t.getChildCount() - 1; i >= 0; --i) {
final ActivityRecord r = t.getChildAt(i);
- if (r.visible && !r.finishing) {
+ if (r.visible && !r.mDrawn && !r.finishing) {
return true;
}
}
@@ -574,19 +572,20 @@
return;
}
- // Check if there is any activity in the task that is visible and not finishing. If the
- // launched activity finished before it is drawn and if there is another activity in
- // the task then that activity will be draw on screen.
- if (hasVisibleNonFinishingActivity(t)) {
+ // If the task of the launched activity contains any activity to be drawn, then the
+ // window drawn event should report later to complete the transition. Otherwise all
+ // activities in this task may be finished, invisible or drawn, so the transition event
+ // should be cancelled.
+ if (hasActivityToBeDrawn(t)) {
return;
}
if (DEBUG_METRICS) Slog.i(TAG, "notifyVisibilityChanged to invisible activity=" + r);
logAppTransitionCancel(info);
- mWindowingModeTransitionInfo.remove(r.getWindowingMode());
- if (mWindowingModeTransitionInfo.size() == 0) {
- reset(true /* abort */, info, "notifyVisibilityChanged to invisible",
- 0L /* timestampNs */);
+ // Abort if this is the only one active transition.
+ if (mWindowingModeTransitionInfo.size() == 1
+ && mWindowingModeTransitionInfo.get(r.getWindowingMode()) != null) {
+ abort(info, "notifyVisibilityChanged to invisible");
}
}
}
@@ -622,19 +621,25 @@
&& mWindowingModeTransitionInfo.size() > 0;
}
+ /** Aborts tracking of current launch metrics. */
+ private void abort(WindowingModeTransitionInfo info, String cause) {
+ reset(true /* abort */, info, cause, 0L /* timestampNs */);
+ }
+
private void reset(boolean abort, WindowingModeTransitionInfo info, String cause,
- long timestampNs) {
+ long timestampNs) {
+ final boolean isAnyTransitionActive = isAnyTransitionActive();
if (DEBUG_METRICS) {
- Slog.i(TAG,
- "reset abort=" + abort + ",cause=" + cause + ",timestamp=" + timestampNs);
+ Slog.i(TAG, "reset abort=" + abort + " cause=" + cause + " timestamp=" + timestampNs
+ + " active=" + isAnyTransitionActive);
}
- if (!abort && isAnyTransitionActive()) {
+ if (!abort && isAnyTransitionActive) {
logAppTransitionMultiEvents();
}
stopLaunchTrace(info);
// Ignore reset-after reset.
- if (isAnyTransitionActive()) {
+ if (isAnyTransitionActive) {
// LaunchObserver callbacks.
if (abort) {
launchObserverNotifyActivityLaunchCancelled(info);
@@ -818,7 +823,14 @@
return StatsLog.APP_START_OCCURRED__TYPE__HOT;
}
return StatsLog.APP_START_OCCURRED__TYPE__UNKNOWN;
- }
+ }
+
+ /** @return the last known window drawn delay of the given windowing mode. */
+ int getLastDrawnDelayMs(@WindowingMode int windowingMode) {
+ final WindowingModeTransitionInfo info = mLastWindowingModeTransitionInfo.get(
+ windowingMode);
+ return info != null ? info.windowsDrawnDelayMs : INVALID_DELAY;
+ }
WindowingModeTransitionInfoSnapshot logAppTransitionReportedDrawn(ActivityRecord r,
boolean restoredFromBundle) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index ec0900f..8aa5e77 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -179,7 +179,7 @@
import static com.android.server.wm.AppWindowTokenProto.FROZEN_BOUNDS;
import static com.android.server.wm.AppWindowTokenProto.HIDDEN_REQUESTED;
import static com.android.server.wm.AppWindowTokenProto.HIDDEN_SET_FROM_TRANSFERRED_STARTING_WINDOW;
-import static com.android.server.wm.AppWindowTokenProto.IS_REALLY_ANIMATING;
+import static com.android.server.wm.AppWindowTokenProto.IS_ANIMATING;
import static com.android.server.wm.AppWindowTokenProto.IS_WAITING_FOR_TRANSITION_START;
import static com.android.server.wm.AppWindowTokenProto.LAST_ALL_DRAWN;
import static com.android.server.wm.AppWindowTokenProto.LAST_SURFACE_SHOWING;
@@ -205,16 +205,17 @@
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
import static com.android.server.wm.TaskPersister.DEBUG;
import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
+import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
+import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
-import static com.android.server.wm.WindowManagerService.logWithStack;
import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
-import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
@@ -291,16 +292,17 @@
import android.view.InputApplicationHandle;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
+import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.animation.Animation;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.ReferrerIntent;
-import com.android.internal.R;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.util.XmlUtils;
import com.android.server.AttributeCache;
@@ -315,6 +317,7 @@
import com.android.server.wm.ActivityMetricsLogger.WindowingModeTransitionInfoSnapshot;
import com.android.server.wm.ActivityStack.ActivityState;
import com.android.server.wm.WindowManagerService.H;
+import com.android.server.wm.utils.InsetUtils;
import com.google.android.collect.Sets;
@@ -332,7 +335,6 @@
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
-import java.util.function.Consumer;
/**
* An entry in the history stack, representing an activity.
@@ -374,6 +376,7 @@
* Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
*/
@VisibleForTesting static final int Z_BOOST_BASE = 800570000;
+ static final int INVALID_PID = -1;
final ActivityTaskManagerService mAtmService;
final ActivityInfo info; // activity info provided by developer in AndroidManifest
@@ -551,24 +554,6 @@
private boolean mCurrentLaunchCanTurnScreenOn = true;
/**
- * This gets used during some open/close transitions as well as during a change transition
- * where it represents the starting-state snapshot.
- */
- private AppWindowThumbnail mThumbnail;
- private final Rect mTransitStartRect = new Rect();
-
- /**
- * If we are running an animation, this determines the transition type. Must be one of
- * AppTransition.TRANSIT_* constants.
- */
- private int mTransit;
-
- /**
- * If we are running an animation, this determines the flags during this animation. Must be a
- * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
- */
- private int mTransitFlags;
- /**
* This leash is used to "freeze" the app surface in place after the state change, but before
* the animation is ready to start.
*/
@@ -602,7 +587,6 @@
private long mLastTransactionSequence = Long.MIN_VALUE;
private int mNumInterestingWindows;
private int mNumDrawnWindows;
- boolean inPendingTransaction;
boolean allDrawn;
private boolean mLastAllDrawn;
@@ -664,7 +648,6 @@
// TODO: Have a WindowContainer state for tracking exiting/deferred removal.
boolean mIsExiting;
- boolean mLaunchTaskBehind;
boolean mEnteringAnimation;
boolean mAppStopped;
@@ -676,15 +659,6 @@
ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
- /** Whether this token should be boosted at the top of all app window tokens. */
- @VisibleForTesting boolean mNeedsZBoost;
-
- /** Layer used to constrain the animation to a token's stack bounds. */
- SurfaceControl mAnimationBoundsLayer;
-
- /** Whether this token needs to create mAnimationBoundsLayer for cropping animations. */
- boolean mNeedsAnimationBoundsLayer;
-
private AppSaturationInfo mLastAppSaturationInfo;
private final ColorDisplayService.ColorTransformController mColorTransformController =
@@ -710,10 +684,6 @@
private final Configuration mTmpConfig = new Configuration();
private final Rect mTmpBounds = new Rect();
- private final Point mTmpPoint = new Point();
- private final Rect mTmpRect = new Rect();
- private final Rect mTmpPrevBounds = new Rect();
-
// Token for targeting this activity for assist purposes.
final Binder assistToken = new Binder();
@@ -905,15 +875,10 @@
pw.print(prefix); pw.print("mNumInterestingWindows=");
pw.print(mNumInterestingWindows);
pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
- pw.print(" inPendingTransaction="); pw.print(inPendingTransaction);
pw.print(" allDrawn="); pw.print(allDrawn);
pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
pw.println(")");
}
- if (inPendingTransaction) {
- pw.print(prefix); pw.print("inPendingTransaction=");
- pw.println(inPendingTransaction);
- }
if (mStartingData != null || removed || firstWindowDrawn || mIsExiting) {
pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
pw.print(" removed="); pw.print(removed);
@@ -1183,56 +1148,11 @@
}
}
- // TODO(task-unify): Remove once TaskRecord and Task are unified.
TaskRecord getTaskRecord() {
return task;
}
/**
- * Sets reference to the {@link TaskRecord} the {@link ActivityRecord} will treat as its parent.
- * Note that this does not actually add the {@link ActivityRecord} as a {@link TaskRecord}
- * children. However, this method will clean up references to this {@link ActivityRecord} in
- * {@link ActivityStack}.
- * @param task The new parent {@link TaskRecord}.
- */
- // TODO(task-unify): Can be remove after task level unification. Callers can just use addChild
- void setTask(TaskRecord task) {
- // Do nothing if the {@link TaskRecord} is the same as the current {@link getTaskRecord}.
- if (task != null && task == getTaskRecord()) {
- return;
- }
-
- final ActivityStack oldStack = getActivityStack();
- final ActivityStack newStack = task != null ? task.getStack() : null;
-
- // Inform old stack (if present) of activity removal and new stack (if set) of activity
- // addition.
- if (oldStack != newStack) {
- if (oldStack != null) {
- oldStack.onActivityRemovedFromStack(this);
- }
-
- if (newStack != null) {
- newStack.onActivityAddedToStack(this);
- }
- }
-
- final TaskRecord oldTask = this.task;
- this.task = task;
-
- // This is attaching the activity to the task which we only want to do once.
- // TODO(task-unify): Need to re-work after unifying the task level since it will already
- // have a parent then. Just need to restructure the re-parent case not to do this. NOTE that
- // the reparenting flag passed in can't be used directly for this as it isn't set in
- // ActivityRecord#reparent() case that ends up calling this method.
- if (task != null && getParent() == null) {
- task.addChild(this);
- } else {
- onParentChanged(task, oldTask);
- }
- }
-
- /**
* Sets the Task on this activity for the purposes of re-use during launch where we will
* re-use another activity instead of this one for the launch.
*/
@@ -1247,7 +1167,7 @@
TaskStack getStack() {
final Task task = getTask();
if (task != null) {
- return task.mStack;
+ return task.getTaskStack();
} else {
return null;
}
@@ -1255,8 +1175,8 @@
@Override
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- final TaskRecord oldTask = (oldParent != null) ? ((Task) oldParent).mTaskRecord : null;
- final TaskRecord newTask = (newParent != null) ? ((Task) newParent).mTaskRecord : null;
+ final TaskRecord oldTask = oldParent != null ? (TaskRecord) oldParent : null;
+ final TaskRecord newTask = newParent != null ? (TaskRecord) newParent : null;
this.task = newTask;
super.onParentChanged(newParent, oldParent);
@@ -1265,14 +1185,12 @@
if (oldParent == null && newParent != null) {
// First time we are adding the activity to the system.
- // TODO(task-unify): See if mVoiceInteraction variable is really needed after task level
- // unification.
- mVoiceInteraction = task.mTaskRecord != null && task.mTaskRecord.voiceSession != null;
+ mVoiceInteraction = newTask.voiceSession != null;
mInputDispatchingTimeoutNanos = getInputDispatchingTimeoutLocked(this) * 1000000L;
onDisplayChanged(task.getDisplayContent());
- if (task.mTaskRecord != null) {
- task.mTaskRecord.updateOverrideConfigurationFromLaunchBounds();
- }
+ // TODO(b/36505427): Maybe this call should be moved inside
+ // updateOverrideConfiguration()
+ newTask.updateOverrideConfigurationFromLaunchBounds();
// Make sure override configuration is up-to-date before using to create window
// controller.
updateSizeCompatMode();
@@ -1292,8 +1210,8 @@
if (getDisplayContent() != null) {
getDisplayContent().mClosingApps.remove(this);
}
- } else if (mLastParent != null && mLastParent.mStack != null) {
- task.mStack.mExitingActivities.remove(this);
+ } else if (mLastParent != null && mLastParent.getTaskStack() != null) {
+ task.getTaskStack().mExitingActivities.remove(this);
}
final TaskStack stack = getStack();
@@ -1314,8 +1232,6 @@
// Inform old stack (if present) of activity removal and new stack (if set) of activity
// addition.
if (oldStack != newStack) {
- // TODO(task-unify): Might be better to use onChildAdded and onChildRemoved signal for
- // this once task level is unified.
if (oldStack != null) {
oldStack.onActivityRemovedFromStack(this);
}
@@ -1999,15 +1915,7 @@
ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving activity=%s"
+ " to task=%d at %d", this, task.mTaskId, position);
-
- reparent(newTask.getTask(), position);
- }
-
- // TODO(task-unify): Remove once Task level is unified.
- void onParentChanged(TaskRecord newParent, TaskRecord oldParent) {
- onParentChanged(
- newParent != null ? newParent.mTask : null,
- oldParent != null ? oldParent.mTask : null);
+ reparent(newTask, position);
}
private boolean isHomeIntent(Intent intent) {
@@ -2086,7 +1994,7 @@
/**
* @return Stack value from current task, null if there is no task.
*/
- // TODO: Remove once ActivityStack and TaskStack are unified.
+ // TODO(stack-unify): Remove once ActivityStack and TaskStack are unified.
<T extends ActivityStack> T getActivityStack() {
return task != null ? (T) task.getStack() : null;
}
@@ -2305,7 +2213,7 @@
* 2. App is delayed closing since it might enter PIP.
*/
boolean isClosingOrEnteringPip() {
- return (isAnimating() && hiddenRequested) || mWillCloseOrEnterPip;
+ return (isAnimating(TRANSITION | PARENTS) && hiddenRequested) || mWillCloseOrEnterPip;
}
/**
* @return Whether AppOps allows this package to enter picture-in-picture.
@@ -2374,7 +2282,7 @@
/** Finish all activities in the task with the same affinity as this one. */
void finishActivityAffinity() {
- final ArrayList<ActivityRecord> activities = getTaskRecord().mActivities;
+ final ArrayList<ActivityRecord> activities = getTaskRecord().mChildren;
for (int index = activities.indexOf(this); index >= 0; --index) {
final ActivityRecord cur = activities.get(index);
if (!Objects.equals(cur.taskAffinity, taskAffinity)) {
@@ -2486,7 +2394,7 @@
EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
mUserId, System.identityHashCode(this),
task.mTaskId, shortComponentName, reason);
- final ArrayList<ActivityRecord> activities = task.mActivities;
+ final ArrayList<ActivityRecord> activities = task.mChildren;
final int index = activities.indexOf(this);
if (index < (task.getChildCount() - 1)) {
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
@@ -2540,7 +2448,7 @@
// When finishing the activity preemptively take the snapshot before the app window
// is marked as hidden and any configuration changes take place
if (mAtmService.mWindowManager.mTaskSnapshotController != null) {
- final ArraySet<Task> tasks = Sets.newArraySet(task.mTask);
+ final ArraySet<Task> tasks = Sets.newArraySet(task);
mAtmService.mWindowManager.mTaskSnapshotController.snapshotTasks(tasks);
mAtmService.mWindowManager.mTaskSnapshotController
.addSkipClosingAppSnapshotTasks(tasks);
@@ -2582,7 +2490,8 @@
// In this case, we can set the visibility of all the task overlay activities when
// we detect the last one is finishing to keep them in sync.
if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) {
- for (ActivityRecord taskOverlay : task.mActivities) {
+ for (int i = task.getChildCount() - 1; i >= 0 ; --i) {
+ final ActivityRecord taskOverlay = task.getChildAt(i);
if (!taskOverlay.mTaskOverlay) {
continue;
}
@@ -2854,8 +2763,6 @@
}
/** Note: call {@link #cleanUp(boolean, boolean)} before this method. */
- // TODO(task-unify): Look into consolidating this with TaskRecord.removeChild once we unify
- // task level.
void removeFromHistory(String reason) {
finishActivityResults(Activity.RESULT_CANCELED, null /* resultData */);
makeFinishingLocked();
@@ -3114,7 +3021,7 @@
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
"Removing app %s delayed=%b animation=%s animating=%b", this, delayed,
- getAnimation(), isSelfAnimating());
+ getAnimation(), isAnimating(TRANSITION));
ProtoLog.v(WM_DEBUG_ADD_REMOVE, "removeAppToken: %s"
+ " delayed=%b Callers=%s", this, delayed, Debug.getCallers(4));
@@ -3126,7 +3033,7 @@
// If this window was animating, then we need to ensure that the app transition notifies
// that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
// so add to that list now
- if (isSelfAnimating()) {
+ if (isAnimating(TRANSITION)) {
getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
}
@@ -3474,7 +3381,7 @@
* color mode set to avoid jank in the middle of the transition.
*/
boolean canShowWindows() {
- return allDrawn && !(isReallyAnimating() && hasNonDefaultColorWindow());
+ return allDrawn && !(isAnimating() && hasNonDefaultColorWindow());
}
/**
@@ -3536,17 +3443,17 @@
return forAllWindowsUnchecked(callback, traverseTopToBottom);
}
- @Override
- void forAllActivities(Consumer<ActivityRecord> callback) {
- callback.accept(this);
- }
-
boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
boolean traverseTopToBottom) {
return super.forAllWindows(callback, traverseTopToBottom);
}
@Override
+ boolean forAllActivities(ToBooleanFunction<ActivityRecord> callback) {
+ return callback.apply(this);
+ }
+
+ @Override
protected void setLayer(Transaction t, int layer) {
if (!mSurfaceAnimator.hasLeash()) {
t.setLayer(mSurfaceControl, layer);
@@ -4065,7 +3972,6 @@
// If we are preparing an app transition, then delay changing
// the visibility of this token until we execute that transition.
if (okToAnimate() && appTransition.isTransitionSet()) {
- inPendingTransaction = true;
if (visible) {
displayContent.mOpeningApps.add(this);
mEnteringAnimation = true;
@@ -4099,7 +4005,6 @@
boolean visible, int transit, boolean performLayout, boolean isVoiceInteraction) {
boolean delayed = false;
- inPendingTransaction = false;
// Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
// been set by the app now.
mHiddenSetFromTransferredStartingWindow = false;
@@ -4127,8 +4032,8 @@
if (transit != WindowManager.TRANSIT_UNSET) {
if (mUseTransferredAnimation) {
- runningAppAnimation = isReallyAnimating();
- } else if (applyAnimationLocked(lp, transit, visible, isVoiceInteraction)) {
+ runningAppAnimation = isAnimating();
+ } else if (applyAnimation(lp, transit, visible, isVoiceInteraction)) {
runningAppAnimation = true;
}
delayed = runningAppAnimation;
@@ -4179,21 +4084,14 @@
}
mUseTransferredAnimation = false;
- if (isReallyAnimating()) {
- delayed = true;
- } else {
+ delayed = isAnimating(CHILDREN);
+ if (!delayed) {
// We aren't animating anything, but exiting windows rely on the animation finished
// callback being called in case the ActivityRecord was pretending to be animating,
// which we might have done because we were in closing/opening apps list.
onAnimationFinished();
}
- for (int i = mChildren.size() - 1; i >= 0 && !delayed; i--) {
- if ((mChildren.get(i)).isSelfOrChildAnimating()) {
- delayed = true;
- }
- }
-
if (visibilityChanged) {
if (visible && !delayed) {
// The token was made immediately visible, there will be no entrance animation.
@@ -4208,7 +4106,7 @@
// updated.
// If we're becoming invisible, update the client visibility if we are not running an
// animation. Otherwise, we'll update client visibility in onAnimationFinished.
- if (visible || !isReallyAnimating()) {
+ if (visible || !isAnimating()) {
setClientHidden(!visible);
}
@@ -4656,16 +4554,25 @@
}
/**
- * Check if activity should be moved to RESUMED state. The activity:
- * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
- * - should be focusable
+ * Check if activity should be moved to RESUMED state.
+ * See {@link #shouldBeResumed(ActivityRecord)}
* @param activeActivity the activity that is active or just completed pause action. We won't
* resume if this activity is active.
*/
@VisibleForTesting
boolean shouldResumeActivity(ActivityRecord activeActivity) {
- return shouldMakeActive(activeActivity) && isFocusable() && !isState(RESUMED)
- && getActivityStack().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE;
+ return shouldBeResumed(activeActivity) && !isState(RESUMED);
+ }
+
+ /**
+ * Check if activity should be RESUMED now. The activity:
+ * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
+ * - should be focusable
+ */
+ private boolean shouldBeResumed(ActivityRecord activeActivity) {
+ return shouldMakeActive(activeActivity) && isFocusable()
+ && getActivityStack().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE
+ && canResumeByCompat();
}
/**
@@ -4703,7 +4610,7 @@
}
// Check if position in task allows to become paused
- final int positionInTask = task.mActivities.indexOf(this);
+ final int positionInTask = task.mChildren.indexOf(this);
if (positionInTask == -1) {
throw new IllegalStateException("Activity not found in its task");
}
@@ -5122,7 +5029,7 @@
final @LaunchState int launchState = info != null ? info.getLaunchState() : -1;
mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
windowsDrawnDelayMs, launchState);
- mStackSupervisor.stopWaitingForActivityVisible(this);
+ mStackSupervisor.stopWaitingForActivityVisible(this, windowsDrawnDelayMs);
finishLaunchTickingLocked();
if (task != null) {
task.hasBeenVisible = true;
@@ -5288,13 +5195,13 @@
if (!allDrawn && w.mightAffectAllDrawn()) {
if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
- + ", isAnimationSet=" + isSelfAnimating());
+ + ", isAnimationSet=" + isAnimating(TRANSITION));
if (!w.isDrawnLw()) {
Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
+ " pv=" + w.isVisibleByPolicy()
+ " mDrawState=" + winAnimator.drawStateToString()
+ " ph=" + w.isParentWindowHidden() + " th=" + hiddenRequested
- + " a=" + isSelfAnimating());
+ + " a=" + isAnimating(TRANSITION));
}
}
@@ -5318,7 +5225,7 @@
}
}
} else if (w.isDrawnLw()) {
- onStartingWindowDrawn(SystemClock.uptimeMillis());
+ onStartingWindowDrawn(SystemClock.elapsedRealtimeNanos());
startingDisplayed = true;
}
}
@@ -5327,10 +5234,10 @@
}
/** Called when the starting window for this container is drawn. */
- private void onStartingWindowDrawn(long timestamp) {
+ private void onStartingWindowDrawn(long timestampNs) {
synchronized (mAtmService.mGlobalLock) {
mAtmService.mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(
- getWindowingMode(), timestamp);
+ getWindowingMode(), timestampNs);
}
}
@@ -5350,7 +5257,7 @@
anrActivity = getWaitingHistoryRecordLocked();
anrApp = app;
windowFromSameProcessAsActivity =
- !hasProcess() || app.getPid() == windowPid || windowPid == -1;
+ !hasProcess() || app.getPid() == windowPid || windowPid == INVALID_PID;
}
if (windowFromSameProcessAsActivity) {
@@ -5431,7 +5338,7 @@
return INVALID_TASK_ID;
}
final TaskRecord task = r.task;
- final int activityNdx = task.mActivities.indexOf(r);
+ final int activityNdx = task.mChildren.indexOf(r);
if (activityNdx < 0
|| (onlyRoot && activityNdx > task.findRootIndex(true /* effectiveRoot */))) {
return INVALID_TASK_ID;
@@ -5722,28 +5629,44 @@
}
}
-
@VisibleForTesting
boolean shouldAnimate(int transit) {
+ final Task task = getTask();
+ if (task != null && !task.shouldAnimate()) {
+ return false;
+ }
final boolean isSplitScreenPrimary =
getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
final boolean allowSplitScreenPrimaryAnimation = transit != TRANSIT_WALLPAPER_OPEN;
- // Don't animate while the task runs recents animation but only if we are in the mode
- // where we cancel with deferred screenshot, which means that the controller has
- // transformed the task.
- final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
- if (controller != null && controller.isAnimatingTask(getTask())
- && controller.shouldDeferCancelUntilNextTransition()) {
- return false;
- }
-
// We animate always if it's not split screen primary, and only some special cases in split
// screen primary because it causes issues with stack clipping when we run an un-minimize
// animation at the same time.
return !isSplitScreenPrimary || allowSplitScreenPrimaryAnimation;
}
+ @Override
+ boolean isChangingAppTransition() {
+ final Task task = getTask();
+ if (task != null) {
+ return task.isChangingAppTransition();
+ }
+ return super.isChangingAppTransition();
+ }
+
+ @Override
+ boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
+ boolean isVoiceInteraction) {
+ if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
+ ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
+ "applyAnimation: transition animation is disabled or skipped. "
+ + "container=%s", this);
+ cancelAnimation();
+ return false;
+ }
+ return super.applyAnimation(lp, transit, enter, isVoiceInteraction);
+ }
+
/**
* Creates a layer to apply crop to an animation.
*/
@@ -5757,171 +5680,6 @@
return boundsLayer;
}
- boolean applyAnimationLocked(WindowManager.LayoutParams lp, int transit, boolean enter,
- boolean isVoiceInteraction) {
-
- if (mWmService.mDisableTransitionAnimation || !shouldAnimate(transit)) {
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
- "applyAnimation: transition animation is disabled or skipped. "
- + "atoken=%s", this);
- cancelAnimation();
- return false;
- }
-
- // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
- // to animate and it can cause strange artifacts when we unfreeze the display if some
- // different animation is running.
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AWT#applyAnimationLocked");
- if (okToAnimate()) {
- final AnimationAdapter adapter;
- AnimationAdapter thumbnailAdapter = null;
-
- final int appStackClipMode =
- getDisplayContent().mAppTransition.getAppStackClipMode();
-
- // Separate position and size for use in animators.
- mTmpRect.set(getAnimationBounds(appStackClipMode));
- mTmpPoint.set(mTmpRect.left, mTmpRect.top);
- mTmpRect.offsetTo(0, 0);
-
- final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
- && getDisplayContent().mChangingApps.contains(this);
-
- // Delaying animation start isn't compatible with remote animations at all.
- if (getDisplayContent().mAppTransition.getRemoteAnimationController() != null
- && !mSurfaceAnimator.isAnimationStartDelayed()) {
- RemoteAnimationController.RemoteAnimationRecord adapters =
- getDisplayContent().mAppTransition.getRemoteAnimationController()
- .createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
- (isChanging ? mTransitStartRect : null));
- adapter = adapters.mAdapter;
- thumbnailAdapter = adapters.mThumbnailAdapter;
- } else if (isChanging) {
- final float durationScale = mWmService.getTransitionAnimationScaleLocked();
- mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
- adapter = new LocalAnimationAdapter(
- new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
- getDisplayContent().getDisplayInfo(), durationScale,
- true /* isAppAnimation */, false /* isThumbnail */),
- mWmService.mSurfaceAnimationRunner);
- if (mThumbnail != null) {
- thumbnailAdapter = new LocalAnimationAdapter(
- new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect,
- getDisplayContent().getDisplayInfo(), durationScale,
- true /* isAppAnimation */, true /* isThumbnail */),
- mWmService.mSurfaceAnimationRunner);
- }
- mTransit = transit;
- mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
- } else {
- mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
-
- final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
- if (a != null) {
- // Only apply corner radius to animation if we're not in multi window mode.
- // We don't want rounded corners when in pip or split screen.
- final float windowCornerRadius = !inMultiWindowMode()
- ? getDisplayContent().getWindowCornerRadius()
- : 0;
- adapter = new LocalAnimationAdapter(
- new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
- getDisplayContent().mAppTransition.canSkipFirstFrame(),
- appStackClipMode,
- true /* isAppAnimation */,
- windowCornerRadius),
- mWmService.mSurfaceAnimationRunner);
- if (a.getZAdjustment() == Animation.ZORDER_TOP) {
- mNeedsZBoost = true;
- }
- mTransit = transit;
- mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
- } else {
- adapter = null;
- }
- }
- if (adapter != null) {
- startAnimation(getPendingTransaction(), adapter, !isVisible());
- if (adapter.getShowWallpaper()) {
- mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
- }
- if (thumbnailAdapter != null) {
- mThumbnail.startAnimation(
- getPendingTransaction(), thumbnailAdapter, !isVisible());
- }
- }
- } else {
- cancelAnimation();
- }
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
-
- return isReallyAnimating();
- }
-
- private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
- boolean isVoiceInteraction) {
- final DisplayContent displayContent = getTask().getDisplayContent();
- final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- final int width = displayInfo.appWidth;
- final int height = displayInfo.appHeight;
- ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
- "applyAnimation: atoken=%s", this);
-
- // Determine the visible rect to calculate the thumbnail clip
- final WindowState win = findMainWindow();
- final Rect frame = new Rect(0, 0, width, height);
- final Rect displayFrame = new Rect(0, 0,
- displayInfo.logicalWidth, displayInfo.logicalHeight);
- final Rect insets = new Rect();
- final Rect stableInsets = new Rect();
- Rect surfaceInsets = null;
- final boolean freeform = win != null && win.inFreeformWindowingMode();
- if (win != null) {
- // Containing frame will usually cover the whole screen, including dialog windows.
- // For freeform workspace windows it will not cover the whole screen and it also
- // won't exactly match the final freeform window frame (e.g. when overlapping with
- // the status bar). In that case we need to use the final frame.
- if (freeform) {
- frame.set(win.getFrameLw());
- } else if (win.isLetterboxedAppWindow()) {
- frame.set(getTask().getBounds());
- } else if (win.isDockedResizing()) {
- // If we are animating while docked resizing, then use the stack bounds as the
- // animation target (which will be different than the task bounds)
- frame.set(getTask().getParent().getBounds());
- } else {
- frame.set(win.getContainingFrame());
- }
- surfaceInsets = win.getAttrs().surfaceInsets;
- // XXX(b/72757033): These are insets relative to the window frame, but we're really
- // interested in the insets relative to the frame we chose in the if-blocks above.
- win.getContentInsets(insets);
- win.getStableInsets(stableInsets);
- }
-
- if (mLaunchTaskBehind) {
- // Differentiate the two animations. This one which is briefly on the screen
- // gets the !enter animation, and the other activity which remains on the
- // screen gets the enter animation. Both appear in the mOpeningApps set.
- enter = false;
- }
- ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
- "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
- + "surfaceInsets=%s",
- AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);
- final Configuration displayConfig = displayContent.getConfiguration();
- final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
- displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
- surfaceInsets, stableInsets, isVoiceInteraction, freeform, getTask().mTaskId);
- if (a != null) {
- if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
- final int containingWidth = frame.width();
- final int containingHeight = frame.height();
- a.initialize(containingWidth, containingHeight, width, height);
- a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
- }
- return a;
- }
-
@Override
public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
return mAnimatingActivityRegistry != null
@@ -5941,9 +5699,10 @@
return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
}
+ @Override
boolean isWaitingForTransitionStart() {
final DisplayContent dc = getDisplayContent();
- // TODO: Test for null can be removed once unification is done.
+ // TODO(display-unify): Test for null can be removed once unification is done.
if (dc == null) return false;
return dc.mAppTransition.isTransitionSet()
&& (dc.mOpeningApps.contains(this)
@@ -5998,7 +5757,7 @@
mWmService.mTaskSnapshotController.createTaskSnapshot(
task, 1 /* scaleFraction */);
if (snapshot != null) {
- mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, t, this,
+ mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory, t, this,
snapshot.getGraphicBuffer(), true /* relative */);
}
}
@@ -6069,10 +5828,7 @@
@Override
void prepareSurfaces() {
- // isSelfAnimating also returns true when we are about to start a transition, so we need
- // to check super here.
- final boolean reallyAnimating = super.isSelfAnimating();
- final boolean show = !isHidden() || reallyAnimating;
+ final boolean show = !isHidden() || isAnimating();
if (mSurfaceControl != null) {
if (show && !mLastSurfaceShowing) {
@@ -6100,19 +5856,18 @@
}
void attachThumbnailAnimation() {
- if (!isReallyAnimating()) {
+ if (!isAnimating()) {
return;
}
- final int taskId = getTask().mTaskId;
final GraphicBuffer thumbnailHeader =
- getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(taskId);
+ getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(getTask());
if (thumbnailHeader == null) {
- ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %d", taskId);
+ ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %s", getTask());
return;
}
clearThumbnail();
- mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, getPendingTransaction(),
- this, thumbnailHeader);
+ mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory,
+ getPendingTransaction(), this, thumbnailHeader);
mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
}
@@ -6121,7 +5876,7 @@
* {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
*/
void attachCrossProfileAppsThumbnailAnimation() {
- if (!isReallyAnimating()) {
+ if (!isAnimating()) {
return;
}
clearThumbnail();
@@ -6140,7 +5895,7 @@
if (thumbnail == null) {
return;
}
- mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory,
+ mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory,
getPendingTransaction(), this, thumbnail);
final Animation animation =
getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
@@ -6161,22 +5916,11 @@
final Rect insets = win != null ? win.getContentInsets() : null;
final Configuration displayConfig = mDisplayContent.getConfiguration();
return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
- appRect, insets, thumbnailHeader, getTask().mTaskId, displayConfig.uiMode,
+ appRect, insets, thumbnailHeader, getTask(), displayConfig.uiMode,
displayConfig.orientation);
}
@Override
- boolean isAppAnimating() {
- return isSelfAnimating();
- }
-
- @Override
- boolean isSelfAnimating() {
- // If we are about to start a transition, we also need to be considered animating.
- return isWaitingForTransitionStart() || isReallyAnimating();
- }
-
- @Override
public void onAnimationLeashLost(Transaction t) {
super.onAnimationLeashLost(t);
if (mAnimationBoundsLayer != null) {
@@ -6281,15 +6025,6 @@
}
}
- /**
- * @return True if and only if we are actually running an animation. Note that
- * {@link #isSelfAnimating} also returns true if we are waiting for an animation to
- * start.
- */
- private boolean isReallyAnimating() {
- return super.isSelfAnimating();
- }
-
@Override
void cancelAnimation() {
cancelAnimationOnly();
@@ -6308,7 +6043,7 @@
}
@VisibleForTesting
- AppWindowThumbnail getThumbnail() {
+ WindowContainerThumbnail getThumbnail() {
return mThumbnail;
}
@@ -6691,6 +6426,7 @@
}
@VisibleForTesting
+ @Override
Rect getAnimationBounds(int appStackClipMode) {
if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
// Using the stack bounds here effectively applies the clipping before animation.
@@ -6774,8 +6510,7 @@
// If the changes come from change-listener, the incoming parent configuration is
// still the old one. Make sure their orientations are the same to reduce computing
// the compatibility bounds for the intermediate state.
- && (task.mTaskRecord == null || task.mTaskRecord
- .getConfiguration().orientation == newParentConfig.orientation)) {
+ && (task.getConfiguration().orientation == newParentConfig.orientation)) {
final Rect taskBounds = task.getBounds();
// Since we only center the activity horizontally, if only the fixed height is smaller
// than its container, the override bounds don't need to take effect.
@@ -7093,8 +6828,7 @@
preserveWindow &= isResizeOnlyChange(changes);
final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
if (hasResizeChange) {
- final boolean isDragResizing =
- getTaskRecord().getTask().isDragResizing();
+ final boolean isDragResizing = getTaskRecord().isDragResizing();
mRelaunchReason = isDragResizing ? RELAUNCH_REASON_FREE_RESIZE
: RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
} else {
@@ -7112,23 +6846,14 @@
deferRelaunchUntilPaused = true;
preserveWindowOnDeferredRelaunch = preserveWindow;
return true;
- } else if (mState == RESUMED) {
- // Try to optimize this case: the configuration is changing and we need to restart
- // the top, resumed activity. Instead of doing the normal handshaking, just say
- // "restart!".
- if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
- "Config is relaunching resumed " + this);
-
- if (DEBUG_STATES && !visible) {
- Slog.v(TAG_STATES, "Config is relaunching resumed invisible activity " + this
- + " called by " + Debug.getCallers(4));
- }
-
- relaunchActivityLocked(true /* andResume */, preserveWindow);
} else {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
- "Config is relaunching non-resumed " + this);
- relaunchActivityLocked(false /* andResume */, preserveWindow);
+ "Config is relaunching " + this);
+ if (DEBUG_STATES && !visible) {
+ Slog.v(TAG_STATES, "Config is relaunching invisible activity " + this
+ + " called by " + Debug.getCallers(4));
+ }
+ relaunchActivityLocked(preserveWindow);
}
// All done... tell the caller we weren't able to keep this activity around.
@@ -7226,12 +6951,13 @@
| CONFIG_SCREEN_LAYOUT)) != 0;
}
- void relaunchActivityLocked(boolean andResume, boolean preserveWindow) {
+ void relaunchActivityLocked(boolean preserveWindow) {
if (mAtmService.mSuppressResizeConfigChanges && preserveWindow) {
configChangeFlags = 0;
return;
}
+ final boolean andResume = shouldBeResumed(null /*activeActivity*/);
List<ResultInfo> pendingResults = null;
List<ReferrerIntent> pendingNewIntents = null;
if (andResume) {
@@ -7643,7 +7369,7 @@
super.writeToProto(proto, WINDOW_TOKEN, logLevel);
proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
- proto.write(IS_REALLY_ANIMATING, isReallyAnimating());
+ proto.write(IS_ANIMATING, isAnimating());
if (mThumbnail != null){
mThumbnail.writeToProto(proto, THUMBNAIL);
}
@@ -7765,4 +7491,35 @@
System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
}
}
+
+ @Override
+ RemoteAnimationTarget createRemoteAnimationTarget(
+ RemoteAnimationController.RemoteAnimationRecord record) {
+ final Task task = getTask();
+ final WindowState mainWindow = findMainWindow();
+ if (task == null || mainWindow == null) {
+ return null;
+ }
+ final Rect insets = new Rect();
+ mainWindow.getContentInsets(insets);
+ InsetUtils.addInsets(insets, getLetterboxInsets());
+ return new RemoteAnimationTarget(task.mTaskId, record.getMode(),
+ record.mAdapter.mCapturedLeash, !task.fillsParent(),
+ mainWindow.mWinAnimator.mLastClipRect, insets,
+ getPrefixOrderIndex(), record.mAdapter.mPosition,
+ record.mAdapter.mStackBounds, task.getWindowConfiguration(),
+ false /*isNotInRecents*/,
+ record.mThumbnailAdapter != null ? record.mThumbnailAdapter.mCapturedLeash : null,
+ record.mStartBounds);
+ }
+
+ @Override
+ void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
+ Rect outSurfaceInsets) {
+ final WindowState win = findMainWindow();
+ if (win == null) {
+ return;
+ }
+ win.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
+ }
}
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 8e3995bf..7df1c15 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -254,7 +254,11 @@
@Override
protected void onParentChanged(
ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- ActivityDisplay display = getParent();
+ if (oldParent != null) {
+ mPrevDisplayId = ((ActivityDisplay) oldParent).mDisplayId;
+ }
+
+ final ActivityDisplay display = getParent();
if (display != null) {
// Rotations are relative to the display. This means if there are 2 displays rotated
// differently (eg. 2 monitors with one landscape and one portrait), moving a stack
@@ -292,18 +296,6 @@
RESTARTING_PROCESS
}
- @VisibleForTesting
- /* The various modes for the method {@link #removeTask}. */
- // Task is being completely removed from all stacks in the system.
- protected static final int REMOVE_TASK_MODE_DESTROYING = 0;
- // Task is being removed from this stack so we can add it to another stack. In the case we are
- // moving we don't want to perform some operations on the task like removing it from window
- // manager or recents.
- static final int REMOVE_TASK_MODE_MOVING = 1;
- // Similar to {@link #REMOVE_TASK_MODE_MOVING} and the task will be added to the top of its new
- // stack and the new stack will be on top of all stacks.
- static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2;
-
final ActivityTaskManagerService mService;
final WindowManagerService mWindowManager;
@@ -381,6 +373,8 @@
final int mStackId;
/** The attached Display's unique identifier, or -1 if detached */
int mDisplayId;
+ // Id of the previous display the stack was on.
+ int mPrevDisplayId = INVALID_DISPLAY;
/** Stores the override windowing-mode from before a transient mode change (eg. split) */
private int mRestoreOverrideWindowingMode = WINDOWING_MODE_UNDEFINED;
@@ -489,8 +483,8 @@
int numActivities() {
int count = 0;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- count += mTaskHistory.get(taskNdx).getChildCount();
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ count += getChildAt(taskNdx).getChildCount();
}
return count;
}
@@ -962,7 +956,7 @@
void positionChildWindowContainerAtTop(TaskRecord child) {
if (mTaskStack != null) {
// TODO: Remove after unification. This cannot be false after that.
- mTaskStack.positionChildAtTop(child.getTask(), true /* includingParents */);
+ mTaskStack.positionChildAtTop(child, true /* includingParents */);
}
}
@@ -974,7 +968,7 @@
child.getStack(), true /* ignoreCurrent */);
if (mTaskStack != null) {
// TODO: Remove after unification. This cannot be false after that.
- mTaskStack.positionChildAtBottom(child.getTask(),
+ mTaskStack.positionChildAtBottom(child,
nextFocusableStack == null /* includingParents */);
}
}
@@ -1062,14 +1056,14 @@
void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
outActivities.clear();
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- mTaskHistory.get(taskNdx).getAllRunningVisibleActivitiesLocked(outActivities);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ getChildAt(taskNdx).getAllRunningVisibleActivitiesLocked(outActivities);
}
}
ActivityRecord topRunningActivityLocked(boolean focusableOnly) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked();
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ ActivityRecord r = getChildAt(taskNdx).topRunningActivityLocked();
if (r != null && (!focusableOnly || r.isFocusable())) {
return r;
}
@@ -1078,8 +1072,8 @@
}
ActivityRecord topRunningNonOverlayTaskActivity() {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (!r.finishing && !r.mTaskOverlay) {
@@ -1091,8 +1085,8 @@
}
ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (!r.finishing && !r.delayedResume && r != notTop && r.okToShowLocked()) {
@@ -1113,8 +1107,8 @@
* @return Returns the HistoryRecord of the next activity on the stack.
*/
final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ TaskRecord task = getChildAt(taskNdx);
if (task.mTaskId == taskId) {
continue;
}
@@ -1130,8 +1124,8 @@
}
ActivityRecord getTopActivity() {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final ActivityRecord r = mTaskHistory.get(taskNdx).getTopActivity();
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final ActivityRecord r = getChildAt(taskNdx).getTopActivity();
if (r != null) {
return r;
}
@@ -1140,16 +1134,16 @@
}
final TaskRecord topTask() {
- final int size = mTaskHistory.size();
+ final int size = getChildCount();
if (size > 0) {
- return mTaskHistory.get(size - 1);
+ return getChildAt(size - 1);
}
return null;
}
TaskRecord taskForIdLocked(int id) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
if (task.mTaskId == id) {
return task;
}
@@ -1168,7 +1162,7 @@
}
final TaskRecord task = r.getTaskRecord();
final ActivityStack stack = r.getActivityStack();
- if (stack != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
+ if (stack != null && task.mChildren.contains(r) && mTaskHistory.contains(task)) {
if (stack != this) Slog.w(TAG,
"Illegal state! task does not point to stack it is in.");
return r;
@@ -1182,8 +1176,10 @@
/** Checks if there are tasks with specific UID in the stack. */
boolean isUidPresent(int uid) {
- for (TaskRecord task : mTaskHistory) {
- for (ActivityRecord r : task.mActivities) {
+ for (int j = getChildCount() - 1; j >= 0; --j) {
+ final TaskRecord task = getChildAt(j);
+ for (int i = task.getChildCount() - 1; i >= 0 ; --i) {
+ final ActivityRecord r = task.getChildAt(i);
if (r.getUid() == uid) {
return true;
}
@@ -1194,8 +1190,10 @@
/** Get all UIDs that are present in the stack. */
void getPresentUIDs(IntArray presentUIDs) {
- for (TaskRecord task : mTaskHistory) {
- for (ActivityRecord r : task.mActivities) {
+ for (int j = getChildCount() - 1; j >= 0; --j) {
+ final TaskRecord task = getChildAt(j);
+ for (int i = task.getChildCount() - 1; i >= 0 ; --i) {
+ final ActivityRecord r = task.getChildAt(i);
presentUIDs.add(r.getUid());
}
}
@@ -1207,12 +1205,6 @@
return display != null && display.isSingleTaskInstance();
}
- private void removeActivitiesFromLRUList(TaskRecord task) {
- for (ActivityRecord r : task.mActivities) {
- mLRUActivities.remove(r);
- }
- }
-
/** @return {@code true} if LRU list contained the specified activity. */
final boolean removeActivityFromLRUList(ActivityRecord activity) {
return mLRUActivities.remove(activity);
@@ -1234,8 +1226,8 @@
private boolean returnsToHomeStack() {
return !inMultiWindowMode()
- && !mTaskHistory.isEmpty()
- && mTaskHistory.get(0).returnsToHomeStack();
+ && hasChild()
+ && getChildAt(0).returnsToHomeStack();
}
void moveToFront(String reason) {
@@ -1338,8 +1330,8 @@
Uri documentData = isDocument ? intent.getData() : null;
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + this);
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
if (task.voiceSession != null) {
// We never match voice sessions; those always run independently.
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session");
@@ -1429,8 +1421,8 @@
}
final int userId = UserHandle.getUserId(info.applicationInfo.uid);
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (!r.okToShowLocked()) {
@@ -1463,9 +1455,9 @@
mCurrentUser = userId;
// Move userId's tasks to the top.
- int index = mTaskHistory.size();
+ int index = getChildCount();
for (int i = 0; i < index; ) {
- final TaskRecord task = mTaskHistory.get(i);
+ final TaskRecord task = getChildAt(i);
if (task.okToShowLocked()) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "switchUser: stack=" + getStackId() +
@@ -1497,8 +1489,8 @@
void awakeFromSleepingLocked() {
// Ensure activities are no longer sleeping.
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
r.setSleeping(false);
@@ -1514,8 +1506,8 @@
final String packageName = aInfo.packageName;
final int userId = UserHandle.getUserId(aInfo.uid);
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord ar = task.getChildAt(activityNdx);
@@ -1592,8 +1584,8 @@
// Make sure any paused or stopped but visible activities are now sleeping.
// This ensures that the activity's onStop() is called.
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (r.isState(STARTED, STOPPING, STOPPED, PAUSED, PAUSING)) {
@@ -1792,8 +1784,7 @@
if (prev.deferRelaunchUntilPaused) {
// Complete the deferred relaunch that was waiting for pause to complete.
if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
- prev.relaunchActivityLocked(false /* andResume */,
- prev.preserveWindowOnDeferredRelaunch);
+ prev.relaunchActivityLocked(prev.preserveWindowOnDeferredRelaunch);
} else if (wasStopping) {
// We are also stopping, the stop request must have gone soon after the pause.
// We can't clobber it, because the stop confirmation will not be handled.
@@ -1877,8 +1868,8 @@
if (!isAttached() || mForceHidden) {
return true;
}
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
@@ -2058,8 +2049,8 @@
final int rankTaskLayers(int baseLayer) {
int layer = 0;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
ActivityRecord r = task.topRunningActivityLocked();
if (r == null || r.finishing || !r.visible) {
task.mLayerRank = -1;
@@ -2109,8 +2100,8 @@
// to be visible (such as performing Recents animation).
final boolean resumeTopActivity = isFocusable() && isInStackLocked(starting) == null
&& top != null && !top.mLaunchTaskBehind;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
final boolean isTop = r == top;
@@ -2207,8 +2198,8 @@
}
void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- mTaskHistory.get(taskNdx).addStartingWindowsForVisibleActivities(taskSwitch);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ getChildAt(taskNdx).addStartingWindowsForVisibleActivities(taskSwitch);
}
}
@@ -2353,8 +2344,8 @@
}
void clearOtherAppTimeTrackers(AppTimeTracker except) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if ( r.appTimeTracker != except) {
@@ -2427,8 +2418,8 @@
}
final ActivityRecord topActivity = topRunningActivityLocked();
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (aboveTop) {
@@ -2980,7 +2971,7 @@
int getAdjustedPositionForTask(TaskRecord task, int suggestedPosition,
ActivityRecord starting) {
- int maxPosition = mTaskHistory.size();
+ int maxPosition = getChildCount();
if ((starting != null && starting.okToShowLocked())
|| (starting == null && task.okToShowLocked())) {
// If the task or starting activity can be shown, then whatever position is okay.
@@ -2989,7 +2980,7 @@
// The task can't be shown, put non-current user tasks below current user tasks.
while (maxPosition > 0) {
- final TaskRecord tmpTask = mTaskHistory.get(maxPosition - 1);
+ final TaskRecord tmpTask = getChildAt(maxPosition - 1);
if (!mStackSupervisor.isCurrentProfileLocked(tmpTask.mUserId)
|| tmpTask.topRunningActivityLocked() == null) {
break;
@@ -3005,7 +2996,7 @@
* @see ActivityTaskManagerService#positionTaskInStack(int, int, int).
*/
private void insertTaskAtPosition(TaskRecord task, int position) {
- if (position >= mTaskHistory.size()) {
+ if (position >= getChildCount()) {
insertTaskAtTop(task, null);
return;
} else if (position <= 0) {
@@ -3016,19 +3007,19 @@
mTaskHistory.remove(task);
mTaskHistory.add(position, task);
if (mTaskStack != null) {
- // TODO: this could not be false after unification.
- mTaskStack.positionChildAt(task.getTask(), position);
+ // TODO: this can not be false after unification Stack.
+ mTaskStack.positionChildAt(task, position);
}
- updateTaskMovement(task, true);
+ task.updateTaskMovement(true);
}
- private void insertTaskAtTop(TaskRecord task, ActivityRecord starting) {
- // TODO: Better place to put all the code below...may be addTask...
+ void insertTaskAtTop(TaskRecord task, ActivityRecord starting) {
+ // TODO: Better place to put all the code below...may be addChild...
mTaskHistory.remove(task);
// Now put task at top.
- final int position = getAdjustedPositionForTask(task, mTaskHistory.size(), starting);
+ final int position = getAdjustedPositionForTask(task, getChildCount(), starting);
mTaskHistory.add(position, task);
- updateTaskMovement(task, true);
+ task.updateTaskMovement(true);
positionChildWindowContainerAtTop(task);
}
@@ -3036,7 +3027,7 @@
mTaskHistory.remove(task);
final int position = getAdjustedPositionForTask(task, 0, null);
mTaskHistory.add(position, task);
- updateTaskMovement(task, true);
+ task.updateTaskMovement(true);
positionChildWindowContainerAtBottom(task);
}
@@ -3057,8 +3048,8 @@
if (!newTask) {
// If starting in an existing task, find where that is...
boolean startIt = true;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ task = getChildAt(taskNdx);
if (task.getTopActivity() == null) {
// All activities in task are finishing.
continue;
@@ -3070,7 +3061,7 @@
if (!startIt) {
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
+ task, new RuntimeException("here").fillInStackTrace());
- r.setTask(rTask);
+ rTask.positionChildAtTop(r);
ActivityOptions.abort(options);
return;
}
@@ -3086,7 +3077,7 @@
// If we are not placing the new activity frontmost, we do not want to deliver the
// onUserLeaving callback to the actual frontmost activity
final TaskRecord activityTask = r.getTaskRecord();
- if (task == activityTask && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
+ if (task == activityTask && mTaskHistory.indexOf(task) != (getChildCount() - 1)) {
mStackSupervisor.mUserLeaving = false;
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"startActivity() behind front, mUserLeaving=false");
@@ -3097,7 +3088,7 @@
// Slot the activity into the history stack and proceed
if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
new RuntimeException("here").fillInStackTrace());
- r.setTask(task);
+ task.positionChildAtTop(r);
// The transition animation and starting window are not needed if {@code allowMoveToFront}
// is false, because the activity won't be visible.
@@ -3272,8 +3263,8 @@
// with the same affinity is unlikely to be in the same stack.
final TaskRecord targetTask;
final ActivityRecord bottom =
- !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
- mTaskHistory.get(0).getChildAt(0) : null;
+ hasChild() && getChildAt(0).hasChild() ?
+ getChildAt(0).getChildAt(0) : null;
if (bottom != null && target.taskAffinity.equals(bottom.getTaskRecord().affinity)) {
// If the activity currently at the bottom has the
// same task affinity as the one we are moving,
@@ -3375,7 +3366,7 @@
if (singleTaskInstanceDisplay || display.alwaysCreateStack(getWindowingMode(),
getActivityType())) {
for (int index = numTasksCreated - 1; index >= 0; index--) {
- final TaskRecord targetTask = mTaskHistory.get(index);
+ final TaskRecord targetTask = getChildAt(index);
final ActivityStack targetStack = display.getOrCreateStack(getWindowingMode(),
getActivityType(), false /* onTop */);
targetTask.reparent(targetStack, false /* toTop */,
@@ -3483,7 +3474,7 @@
// instance of the same activity? Then we drop the instance
// below so it remains singleTop.
if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
- final ArrayList<ActivityRecord> taskActivities = task.mActivities;
+ final ArrayList<ActivityRecord> taskActivities = task.mChildren;
final int targetNdx = taskActivities.indexOf(target);
if (targetNdx > 0) {
final ActivityRecord p = taskActivities.get(targetNdx - 1);
@@ -3526,8 +3517,8 @@
// Preserve the location for reparenting in the new task.
int reparentInsertionPoint = -1;
- for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
- final TaskRecord targetTask = mTaskHistory.get(i);
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final TaskRecord targetTask = getChildAt(i);
if (targetTask == task) {
topOptions = resetTargetTaskIfNeededLocked(task, forceReset);
@@ -3540,7 +3531,7 @@
int taskNdx = mTaskHistory.indexOf(task);
if (taskNdx >= 0) {
- ActivityRecord newTop = mTaskHistory.get(taskNdx).getTopActivity();
+ ActivityRecord newTop = getChildAt(taskNdx).getTopActivity();
if (newTop != null) {
taskTop = newTop;
}
@@ -3603,8 +3594,8 @@
/** Finish all activities that were started for result from the specified activity. */
final void finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (r.resultTo == self && r.requestCode == requestCode) {
@@ -3637,7 +3628,7 @@
finishedTask = r.getTaskRecord();
int taskNdx = mTaskHistory.indexOf(finishedTask);
final TaskRecord task = finishedTask;
- int activityNdx = task.mActivities.indexOf(r);
+ int activityNdx = task.mChildren.indexOf(r);
getDisplay().mDisplayContent.prepareAppTransition(
TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
r.finishIfPossible(reason, false /* oomAdj */);
@@ -3652,11 +3643,11 @@
if (taskNdx < 0) {
break;
}
- activityNdx = mTaskHistory.get(taskNdx).getChildCount() - 1;
+ activityNdx = getChildAt(taskNdx).getChildCount() - 1;
} while (activityNdx < 0);
}
if (activityNdx >= 0) {
- r = mTaskHistory.get(taskNdx).getChildAt(activityNdx);
+ r = getChildAt(taskNdx).getChildAt(activityNdx);
if (r.isState(STARTED, RESUMED, PAUSING, PAUSED)) {
if (!r.isActivityTypeHome() || mService.mHomeProcess != r.app) {
Slog.w(TAG, " Force finishing activity "
@@ -3671,8 +3662,8 @@
final void finishVoiceTask(IVoiceInteractionSession session) {
IBinder sessionBinder = session.asBinder();
boolean didOne = false;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- TaskRecord tr = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ TaskRecord tr = getChildAt(taskNdx);
if (tr.voiceSession != null && tr.voiceSession.asBinder() == sessionBinder) {
for (int activityNdx = tr.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord r = tr.getChildAt(activityNdx);
@@ -3709,8 +3700,8 @@
/** Finish all activities in the stack without waiting. */
void finishAllActivitiesImmediately() {
boolean noActivitiesInStack = true;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
noActivitiesInStack = false;
@@ -3762,7 +3753,7 @@
Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec);
return false;
}
- final TaskRecord prevTask = mTaskHistory.get(taskIdx);
+ final TaskRecord prevTask = getChildAt(taskIdx);
if (!task.affinity.equals(prevTask.affinity)) {
// These are different apps, so need to recreate.
return true;
@@ -3774,7 +3765,7 @@
final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
Intent resultData) {
final TaskRecord task = srec.getTaskRecord();
- final ArrayList<ActivityRecord> activities = task.mActivities;
+ final ArrayList<ActivityRecord> activities = task.mChildren;
final int start = activities.indexOf(srec);
if (!mTaskHistory.contains(task) || (start < 0)) {
return false;
@@ -3868,8 +3859,16 @@
* an activity moves away from the stack.
*/
void onActivityRemovedFromStack(ActivityRecord r) {
+ removeActivityFromLRUList(r);
removeTimeoutsForActivity(r);
+ // TODO(stack-unify): null check will no longer be needed.
+ if (mTaskStack != null) {
+ mTaskStack.mExitingActivities.remove(r);
+ }
+ // TODO(stack-unify): Remove if no bugs showed up...
+ //r.mIsExiting = false;
+
if (mResumedActivity != null && mResumedActivity == r) {
setResumedActivity(null, "onActivityRemovedFromStack");
}
@@ -3945,8 +3944,8 @@
private void destroyActivitiesLocked(WindowProcessController owner, String reason) {
boolean lastIsOpaque = false;
boolean activityRemoved = false;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (r.finishing) {
@@ -3986,8 +3985,8 @@
maxTasks = 1;
}
int numReleased = 0;
- for (int taskNdx = 0; taskNdx < mTaskHistory.size() && maxTasks > 0; taskNdx++) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = 0; taskNdx < getChildCount() && maxTasks > 0; taskNdx++) {
+ final TaskRecord task = getChildAt(taskNdx);
if (!tasks.contains(task)) {
continue;
}
@@ -4010,7 +4009,7 @@
if (curNum > 0) {
numReleased += curNum;
maxTasks--;
- if (mTaskHistory.get(taskNdx) != task) {
+ if (getChildAt(taskNdx) != task) {
// The entire task got removed, back up so we don't miss the next one.
taskNdx--;
}
@@ -4061,8 +4060,8 @@
int i = numActivities();
if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
"Removing app " + app + " from history with " + i + " entries");
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final ArrayList<ActivityRecord> activities = getChildAt(taskNdx).mChildren;
mTmpActivities.clear();
mTmpActivities.addAll(activities);
@@ -4151,26 +4150,13 @@
getDisplay().mDisplayContent.prepareAppTransition(transit, false);
}
- private void updateTaskMovement(TaskRecord task, boolean toFront) {
- if (task.isPersistable) {
- task.mLastTimeMoved = System.currentTimeMillis();
- // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
- // recently will be most negative, tasks sent to the bottom before that will be less
- // negative. Similarly for recent tasks moved to the top which will be most positive.
- if (!toFront) {
- task.mLastTimeMoved *= -1;
- }
- }
- mRootActivityContainer.invalidateTaskLayers();
- }
-
final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options,
AppTimeTracker timeTracker, String reason) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
final ActivityStack topStack = getDisplay().getTopStack();
final ActivityRecord topActivity = topStack != null ? topStack.getTopActivity() : null;
- final int numTasks = mTaskHistory.size();
+ final int numTasks = getChildCount();
final int index = mTaskHistory.indexOf(tr);
if (numTasks == 0 || index < 0) {
// nothing to do!
@@ -4296,7 +4282,7 @@
mTaskHistory.remove(tr);
mTaskHistory.add(0, tr);
- updateTaskMovement(tr, false);
+ tr.updateTaskMovement(false);
getDisplay().mDisplayContent.prepareAppTransition(TRANSIT_TASK_TO_BACK, false);
moveToBack("moveTaskToBackLocked", tr);
@@ -4334,8 +4320,8 @@
boolean updatedConfig = false;
for (int taskIndex = mTaskHistory.indexOf(startTask); taskIndex >= 0; --taskIndex) {
- final TaskRecord task = mTaskHistory.get(taskIndex);
- final ArrayList<ActivityRecord> activities = task.mActivities;
+ final TaskRecord task = getChildAt(taskIndex);
+ final ArrayList<ActivityRecord> activities = task.mChildren;
int activityIndex = (start.getTaskRecord() == task)
? activities.indexOf(start) : activities.size() - 1;
for (; activityIndex >= 0; --activityIndex) {
@@ -4371,14 +4357,14 @@
try {
// Update override configurations of all tasks in the stack.
final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds;
- for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
- final TaskRecord task = mTaskHistory.get(i);
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ final TaskRecord task = getChildAt(i);
if (task.isResizeable()) {
if (tempTaskInsetBounds != null && !tempTaskInsetBounds.isEmpty()) {
- task.setDisplayedBounds(taskBounds);
+ task.setOverrideDisplayedBounds(taskBounds);
task.setBounds(tempTaskInsetBounds);
} else {
- task.setDisplayedBounds(null);
+ task.setOverrideDisplayedBounds(null);
task.setBounds(taskBounds);
}
}
@@ -4411,8 +4397,8 @@
return;
}
- for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
- final TaskRecord task = mTaskHistory.get(i);
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ final TaskRecord task = getChildAt(i);
if (task.isResizeable()) {
task.setBounds(bounds);
} else {
@@ -4427,19 +4413,19 @@
return;
}
- for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
- final TaskRecord task = mTaskHistory.get(i);
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ final TaskRecord task = getChildAt(i);
if (bounds == null || bounds.isEmpty()) {
- task.setDisplayedBounds(null);
+ task.setOverrideDisplayedBounds(null);
} else if (task.isResizeable()) {
- task.setDisplayedBounds(bounds);
+ task.setOverrideDisplayedBounds(bounds);
}
}
}
boolean willActivityBeVisibleLocked(IBinder token) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (r.appToken == token) {
@@ -4460,8 +4446,8 @@
}
void closeSystemDialogsLocked() {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
@@ -4476,8 +4462,8 @@
boolean didSomething = false;
TaskRecord lastTask = null;
ComponentName homeActivity = null;
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final ArrayList<ActivityRecord> activities = getChildAt(taskNdx).mChildren;
mTmpActivities.clear();
mTmpActivities.addAll(activities);
@@ -4527,8 +4513,8 @@
boolean focusedStack = mRootActivityContainer.getTopDisplayFocusedStack() == this;
boolean topTask = true;
int userId = UserHandle.getUserId(callingUid);
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
if (task.getTopActivity() == null) {
// Skip if there are no activities in the task
continue;
@@ -4567,10 +4553,10 @@
}
void unhandledBackLocked() {
- final int top = mTaskHistory.size() - 1;
+ final int top = getChildCount() - 1;
if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Performing unhandledBack(): top activity at " + top);
if (top >= 0) {
- final TaskRecord task = mTaskHistory.get(top);
+ final TaskRecord task = getChildAt(top);
int activityTop = task.getChildCount() - 1;
if (activityTop >= 0) {
task.getChildAt(activityTop).finishIfPossible("unhandled-back", true /* oomAdj */);
@@ -4598,8 +4584,8 @@
}
void handleAppCrash(WindowProcessController app) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord r = task.getChildAt(activityNdx);
if (r.app == app) {
@@ -4659,12 +4645,12 @@
boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
boolean dumpClient, String dumpPackage, boolean needSep) {
- if (mTaskHistory.isEmpty()) {
+ if (!hasChild()) {
return false;
}
final String prefix = " ";
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
if (needSep) {
pw.println("");
}
@@ -4675,7 +4661,7 @@
pw.println(prefix + "mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds);
pw.println(prefix + "* " + task);
task.dump(pw, prefix + " ");
- dumpHistoryList(fd, pw, mTaskHistory.get(taskNdx).mActivities,
+ dumpHistoryList(fd, pw, getChildAt(taskNdx).mChildren,
prefix, "Hist", true, !dumpAll, dumpClient, dumpPackage, false, null, task);
}
return true;
@@ -4685,24 +4671,26 @@
ArrayList<ActivityRecord> activities = new ArrayList<>();
if ("all".equals(name)) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- activities.addAll(mTaskHistory.get(taskNdx).mActivities);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ activities.addAll(getChildAt(taskNdx).mChildren);
}
} else if ("top".equals(name)) {
- final int top = mTaskHistory.size() - 1;
+ final int top = getChildCount() - 1;
if (top >= 0) {
- final ArrayList<ActivityRecord> list = mTaskHistory.get(top).mActivities;
- int listTop = list.size() - 1;
+ final TaskRecord task = getChildAt(top);
+ int listTop = task.getChildCount() - 1;
if (listTop >= 0) {
- activities.add(list.get(listTop));
+ activities.add(task.getChildAt(listTop));
}
}
} else {
ItemMatcher matcher = new ItemMatcher();
matcher.build(name);
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- for (ActivityRecord r1 : mTaskHistory.get(taskNdx).mActivities) {
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
+ for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
+ final ActivityRecord r1 = task.getChildAt(activityNdx);
if (matcher.match(r1, r1.intent.getComponent())) {
activities.add(r1);
}
@@ -4718,8 +4706,8 @@
// All activities that came from the package must be
// restarted as if there was a config change.
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
final ActivityRecord a = task.getChildAt(activityNdx);
if (a.info.packageName.equals(packageName)) {
@@ -4734,57 +4722,50 @@
return starting;
}
+ // TODO(stack-unify): Merge into removeChild method below.
+ void onChildRemoved(TaskRecord child, DisplayContent dc) {
+ mTaskHistory.remove(child);
+ EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, child.mTaskId, mStackId);
+
+ ActivityDisplay display = getDisplay();
+ if (display == null && dc != null) {
+ display = dc.mActivityDisplay;
+ }
+
+ if (display.isSingleTaskInstance()) {
+ mService.notifySingleTaskDisplayEmpty(display.mDisplayId);
+ }
+
+ display.mDisplayContent.setLayoutNeeded();
+
+ if (!hasChild()) {
+ // Stack is now empty...
+ remove();
+ }
+ }
+
/**
* Removes the input task from this stack.
*
* @param task to remove.
* @param reason for removal.
- * @param mode task removal mode. Either {@link #REMOVE_TASK_MODE_DESTROYING},
- * {@link #REMOVE_TASK_MODE_MOVING}, {@link #REMOVE_TASK_MODE_MOVING_TO_TOP}.
*/
- void removeTask(TaskRecord task, String reason, int mode) {
- if (!mTaskHistory.remove(task)) {
- // Not really in this stack anymore...
- return;
- }
-
- EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, task.mTaskId, getStackId());
-
- removeActivitiesFromLRUList(task);
- updateTaskMovement(task, true);
-
- if (mode == REMOVE_TASK_MODE_DESTROYING) {
- task.cleanUpResourcesForDestroy();
- }
-
+ void removeChild(TaskRecord task, String reason) {
final ActivityDisplay display = getDisplay();
- if (mTaskHistory.isEmpty()) {
- if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this);
+ final boolean topFocused = mRootActivityContainer.isTopDisplayFocusedStack(this);
+ mTaskStack.removeChild(task);
+ moveHomeStackToFrontIfNeeded(topFocused, display, reason);
+ }
+
+ void moveHomeStackToFrontIfNeeded(
+ boolean wasTopFocusedStack, ActivityDisplay display, String reason) {
+ if (!hasChild() && wasTopFocusedStack) {
// We only need to adjust focused stack if this stack is in focus and we are not in the
// process of moving the task to the top of the stack that will be focused.
- if (mode != REMOVE_TASK_MODE_MOVING_TO_TOP
- && mRootActivityContainer.isTopDisplayFocusedStack(this)) {
- String myReason = reason + " leftTaskHistoryEmpty";
- if (!inMultiWindowMode() || adjustFocusToNextFocusableStack(myReason) == null) {
- display.moveHomeStackToFront(myReason);
- }
+ String myReason = reason + " leftTaskHistoryEmpty";
+ if (!inMultiWindowMode() || adjustFocusToNextFocusableStack(myReason) == null) {
+ display.moveHomeStackToFront(myReason);
}
- if (isAttached()) {
- display.positionChildAtBottom(this);
- }
- if (!isActivityTypeHome() || !isAttached()) {
- remove();
- }
- }
-
- task.setStack(null);
-
- // Notify if a task from the pinned stack is being removed (or moved depending on the mode)
- if (inPinnedWindowingMode()) {
- mService.getTaskChangeNotificationController().notifyActivityUnpinned();
- }
- if (display != null && display.isSingleTaskInstance()) {
- mService.notifySingleTaskDisplayEmpty(display.mDisplayId);
}
}
@@ -4800,9 +4781,9 @@
boolean toTop, ActivityRecord activity, ActivityRecord source,
ActivityOptions options) {
final TaskRecord task = TaskRecord.create(
- mService, taskId, info, intent, voiceSession, voiceInteractor);
+ mService, taskId, info, intent, voiceSession, voiceInteractor, this);
// add the task to stack first, mTaskPositioner might need the stack association
- addTask(task, toTop, "createTaskRecord");
+ addChild(task, toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController()
.isKeyguardOrAodShowing(displayId);
@@ -4811,7 +4792,6 @@
&& !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
task.setBounds(getRequestedOverrideBounds());
}
- task.createTask(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
return task;
}
@@ -4819,36 +4799,33 @@
return new ArrayList<>(mTaskHistory);
}
- void addTask(final TaskRecord task, final boolean toTop, String reason) {
- addTask(task, toTop ? MAX_VALUE : 0, true /* schedulePictureInPictureModeChange */, reason);
+ // TODO(stack-unify): Merge with addChild below.
+ void onChildAdded(TaskRecord task, int position) {
+ final boolean toTop = position >= getChildCount();
+ mTaskHistory.add(position, task);
+
+ // TODO: Feels like this should go in TaskRecord#onParentChanged
+ task.updateTaskMovement(toTop);
+ }
+
+ void addChild(final TaskRecord task, final boolean toTop, boolean showForAllUsers) {
+ if (isSingleTaskInstance() && hasChild()) {
+ throw new IllegalStateException("Can only have one child on stack=" + this);
+ }
+
+ final int position =
+ getAdjustedPositionForTask(task, toTop ? MAX_VALUE : 0, null /* starting */);
+
+ // We only want to move the parents to the parents if we are creating this task at the
+ // top of its stack.
+ mTaskStack.addChild(task, position, showForAllUsers, toTop /*moveParents*/);
+
if (toTop) {
// TODO: figure-out a way to remove this call.
positionChildWindowContainerAtTop(task);
}
}
- // TODO: This shouldn't allow automatic reparenting. Remove the call to preAddTask and deal
- // with the fall-out...
- void addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange,
- String reason) {
- // TODO: Is this remove really needed? Need to look into the call path for the other addTask
- mTaskHistory.remove(task);
- if (isSingleTaskInstance() && !mTaskHistory.isEmpty()) {
- throw new IllegalStateException("Can only have one child on stack=" + this);
- }
-
- position = getAdjustedPositionForTask(task, position, null /* starting */);
- final boolean toTop = position >= mTaskHistory.size();
- final ActivityStack prevStack = preAddTask(task, reason, toTop);
-
- mTaskHistory.add(position, task);
- task.setStack(this);
-
- updateTaskMovement(task, toTop);
-
- postAddTask(task, prevStack, schedulePictureInPictureModeChange);
- }
-
void positionChildAt(TaskRecord task, int index) {
if (task.getStack() != this) {
@@ -4861,8 +4838,14 @@
final ActivityRecord topRunningActivity = task.topRunningActivityLocked();
final boolean wasResumed = topRunningActivity == task.getStack().mResumedActivity;
insertTaskAtPosition(task, index);
- task.setStack(this);
- postAddTask(task, null /* prevStack */, true /* schedulePictureInPictureModeChange */);
+
+ // TODO: Investigate if this random code is really needed.
+ if (task.voiceSession != null) {
+ try {
+ task.voiceSession.taskStarted(task.intent, task.mTaskId);
+ } catch (RemoteException e) {
+ }
+ }
if (wasResumed) {
if (mResumedActivity != null) {
@@ -4879,32 +4862,6 @@
mRootActivityContainer.resumeFocusedStacksTopActivities();
}
- private ActivityStack preAddTask(TaskRecord task, String reason, boolean toTop) {
- final ActivityStack prevStack = task.getStack();
- if (prevStack != null && prevStack != this) {
- prevStack.removeTask(task, reason,
- toTop ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
- }
- return prevStack;
- }
-
- /**
- * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
- * change. Callers may set this to false if they are explicitly scheduling PiP mode
- * changes themselves, like during the PiP animation
- */
- private void postAddTask(TaskRecord task, ActivityStack prevStack,
- boolean schedulePictureInPictureModeChange) {
- if (schedulePictureInPictureModeChange && prevStack != null) {
- mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, prevStack);
- } else if (task.voiceSession != null) {
- try {
- task.voiceSession.taskStarted(task.intent, task.mTaskId);
- } catch (RemoteException e) {
- }
- }
- }
-
public void setAlwaysOnTop(boolean alwaysOnTop) {
if (isAlwaysOnTop() == alwaysOnTop) {
return;
@@ -5024,12 +4981,12 @@
+ " visible=" + shouldBeVisible(null /* starting */)
+ " translucent=" + isStackTranslucent(null /* starting */)
+ ", "
- + mTaskHistory.size() + " tasks}";
+ + getChildCount() + " tasks}";
}
void onLockTaskPackagesUpdated() {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- mTaskHistory.get(taskNdx).setLockTaskAuth();
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ getChildAt(taskNdx).setLockTaskAuth();
}
}
@@ -5060,8 +5017,8 @@
final long token = proto.start(fieldId);
super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
proto.write(ID, mStackId);
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
+ for (int taskNdx = getChildCount() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = getChildAt(taskNdx);
task.writeToProto(proto, TASKS, logLevel);
}
if (mResumedActivity != null) {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 64351fb0..f8a7397 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -52,7 +52,6 @@
import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_IDLE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
@@ -82,6 +81,8 @@
import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.wm.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
import android.Manifest;
import android.app.Activity;
@@ -561,8 +562,8 @@
return candidateTaskId;
}
- void waitActivityVisible(ComponentName name, WaitResult result, long startTimeMs) {
- final WaitInfo waitInfo = new WaitInfo(name, result, startTimeMs);
+ void waitActivityVisible(ComponentName name, WaitResult result) {
+ final WaitInfo waitInfo = new WaitInfo(name, result);
mWaitingForActivityVisible.add(waitInfo);
}
@@ -572,10 +573,15 @@
// down to the max limit while they are still waiting to finish.
mFinishingActivities.remove(r);
- stopWaitingForActivityVisible(r);
+ stopWaitingForActivityVisible(r, WaitResult.INVALID_DELAY);
}
void stopWaitingForActivityVisible(ActivityRecord r) {
+ stopWaitingForActivityVisible(r,
+ getActivityMetricsLogger().getLastDrawnDelayMs(r.getWindowingMode()));
+ }
+
+ void stopWaitingForActivityVisible(ActivityRecord r, long totalTime) {
boolean changed = false;
for (int i = mWaitingForActivityVisible.size() - 1; i >= 0; --i) {
final WaitInfo w = mWaitingForActivityVisible.get(i);
@@ -584,7 +590,7 @@
changed = true;
result.timeout = false;
result.who = w.getComponent();
- result.totalTime = SystemClock.uptimeMillis() - w.getStartTime();
+ result.totalTime = totalTime;
mWaitingForActivityVisible.remove(w);
}
}
@@ -1414,7 +1420,7 @@
// WM resizeTask must be done after the task is moved to the correct stack,
// because Task's setBounds() also updates dim layer's bounds, but that has
// dependency on the stack.
- task.resizeWindowContainer();
+ task.resize(false /* relayout */, false /* forced */);
}
}
@@ -1879,26 +1885,22 @@
final ActivityStack stack =
mRootActivityContainer.getLaunchStack(null, aOptions, task, onTop);
final ActivityStack currentStack = task.getStack();
- if (currentStack != null) {
- // Task has already been restored once. See if we need to do anything more
- if (currentStack == stack) {
- // Nothing else to do since it is already restored in the right stack.
- return true;
- }
- // Remove current stack association, so we can re-associate the task with the
- // right stack below.
- currentStack.removeTask(task, "restoreRecentTaskLocked", REMOVE_TASK_MODE_MOVING);
+
+ if (currentStack == stack) {
+ // Nothing else to do since it is already restored in the right stack.
+ return true;
}
- stack.addTask(task, onTop, "restoreRecentTask");
- // TODO: move call for creation here and other place into Stack.addTask()
- task.createTask(onTop, true /* showForAllUsers */);
+ if (currentStack != null) {
+ // Task has already been restored once. Just re-parent it to the new stack.
+ task.reparent(stack.mTaskStack,
+ POSITION_TOP, true /*moveParents*/, "restoreRecentTaskLocked");
+ return true;
+ }
+
+ stack.addChild(task, onTop, true /* showForAllUsers */);
if (DEBUG_RECENTS) Slog.v(TAG_RECENTS,
"Added restored task=" + task + " to stack=" + stack);
- for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
- final ActivityRecord r = task.getChildAt(activityNdx);
- r.setTask(task);
- }
return true;
}
@@ -2127,7 +2129,7 @@
for (int activityNdx = mStoppingActivities.size() - 1; activityNdx >= 0; --activityNdx) {
ActivityRecord s = mStoppingActivities.get(activityNdx);
- final boolean animating = s.isSelfAnimating();
+ final boolean animating = s.isAnimating(TRANSITION);
if (DEBUG_STATES) Slog.v(TAG, "Stopping " + s + ": nowVisible=" + nowVisible
+ " animating=" + animating + " finishing=" + s.finishing);
@@ -2823,13 +2825,10 @@
static class WaitInfo {
private final ComponentName mTargetComponent;
private final WaitResult mResult;
- /** Time stamp when we started to wait for {@link WaitResult}. */
- private final long mStartTimeMs;
- WaitInfo(ComponentName targetComponent, WaitResult result, long startTimeMs) {
+ WaitInfo(ComponentName targetComponent, WaitResult result) {
this.mTargetComponent = targetComponent;
this.mResult = result;
- this.mStartTimeMs = startTimeMs;
}
public boolean matches(ComponentName targetComponent) {
@@ -2840,10 +2839,6 @@
return mResult;
}
- public long getStartTime() {
- return mStartTimeMs;
- }
-
public ComponentName getComponent() {
return mTargetComponent;
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index ff0dc54..6edcb02 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -50,6 +50,7 @@
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
+import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
@@ -107,7 +108,6 @@
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
-import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
@@ -764,9 +764,7 @@
mRequest.waitResult.who = r.mActivityComponent;
mRequest.waitResult.totalTime = 0;
} else {
- final long startTimeMs = SystemClock.uptimeMillis();
- mSupervisor.waitActivityVisible(r.mActivityComponent, mRequest.waitResult,
- startTimeMs);
+ mSupervisor.waitActivityVisible(r.mActivityComponent, mRequest.waitResult);
// Note: the timeout variable is not currently not ever set.
do {
try {
@@ -1845,7 +1843,7 @@
// {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The task
// reference is needed in the call below to {@link setTargetStackAndMoveToFrontIfNeeded}
if (targetTaskTop.getTaskRecord() == null) {
- targetTaskTop.setTask(targetTask);
+ targetTask.addChild(targetTaskTop);
}
if (top != null) {
@@ -1865,8 +1863,8 @@
// Go ahead and reset it.
mTargetStack = computeStackFocus(mSourceRecord, false /* newTask */,
mLaunchFlags, mOptions);
- mTargetStack.addTask(targetTask,
- !mLaunchTaskBehind /* toTop */, "complyActivityFlags");
+ mTargetStack.addChild(targetTask, !mLaunchTaskBehind /* toTop */,
+ (mStartActivity.info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
}
}
} else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) == 0 && !mAddingToTask
@@ -2354,7 +2352,7 @@
mMovedToFront = true;
}
- if (launchStack.topTask() == null) {
+ if (launchStack != null && launchStack.topTask() == null) {
// The task does not need to be reparented to the launch stack. Remove the
// launch stack if there is no activity in it.
Slog.w(TAG, "Removing an empty stack: " + launchStack);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 3da8481..da7af5f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -85,7 +85,6 @@
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.PACKAGE;
import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
@@ -227,6 +226,7 @@
import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
+import android.view.WindowContainerTransaction;
import android.view.WindowManager;
import com.android.internal.R;
@@ -289,6 +289,7 @@
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -1994,7 +1995,7 @@
return false;
}
final TaskRecord task = r.getTaskRecord();
- int index = task.mActivities.lastIndexOf(r);
+ int index = task.mChildren.lastIndexOf(r);
if (index > 0) {
ActivityRecord under = task.getChildAt(index - 1);
under.returningOptions = safeOptions != null ? safeOptions.getOptions(r) : null;
@@ -2219,18 +2220,10 @@
Slog.w(TAG, "getTaskBounds: taskId=" + taskId + " not found");
return rect;
}
- if (task.getStack() != null) {
- // Return the bounds from window manager since it will be adjusted for various
- // things like the presense of a docked stack for tasks that aren't resizeable.
- task.getWindowContainerBounds(rect);
- } else {
- // Task isn't in window manager yet since it isn't associated with a stack.
- // Return the persist value from activity manager
- if (!task.matchParentBounds()) {
- rect.set(task.getBounds());
- } else if (task.mLastNonFullscreenBounds != null) {
- rect.set(task.mLastNonFullscreenBounds);
- }
+ if (task.getParent() != null) {
+ rect.set(task.getBounds());
+ } else if (task.mLastNonFullscreenBounds != null) {
+ rect.set(task.mLastNonFullscreenBounds);
}
}
} finally {
@@ -2247,7 +2240,7 @@
final TaskRecord tr = mRootActivityContainer.anyTaskForId(id,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
if (tr != null) {
- return tr.mTaskDescription;
+ return tr.getTaskDescription();
}
}
return null;
@@ -3166,10 +3159,10 @@
null /* voiceSession */, null /* voiceInteractor */, !ON_TOP);
if (!mRecentTasks.addToBottom(task)) {
// The app has too many tasks already and we can't add any more
- stack.removeTask(task, "addAppTask", REMOVE_TASK_MODE_DESTROYING);
+ stack.removeChild(task, "addAppTask");
return INVALID_TASK_ID;
}
- task.mTaskDescription.copyFrom(description);
+ task.getTaskDescription().copyFrom(description);
// TODO: Send the thumbnail to WM to store it.
@@ -3249,6 +3242,47 @@
}
}
+ private void sanitizeAndApplyConfigChange(ConfigurationContainer container,
+ WindowContainerTransaction.Change change) {
+ if (!(container instanceof TaskRecord)) {
+ throw new RuntimeException("Invalid token in task transaction");
+ }
+ // The "client"-facing API should prevent bad changes; however, just in case, sanitize
+ // masks here.
+ int configMask = change.getConfigSetMask();
+ int windowMask = change.getWindowSetMask();
+ configMask &= ActivityInfo.CONFIG_WINDOW_CONFIGURATION
+ | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
+ windowMask &= WindowConfiguration.WINDOW_CONFIG_BOUNDS;
+ Configuration c = new Configuration(container.getRequestedOverrideConfiguration());
+ c.setTo(change.getConfiguration(), configMask, windowMask);
+ container.onRequestedOverrideConfigurationChanged(c);
+ }
+
+ @Override
+ public void applyContainerTransaction(WindowContainerTransaction t) {
+ mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "applyContainerTransaction()");
+ long ident = Binder.clearCallingIdentity();
+ try {
+ if (t == null) {
+ return;
+ }
+ synchronized (mGlobalLock) {
+ Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries =
+ t.getChanges().entrySet().iterator();
+ while (entries.hasNext()) {
+ final Map.Entry<IBinder, WindowContainerTransaction.Change> entry =
+ entries.next();
+ final ConfigurationContainer cc = ConfigurationContainer.RemoteToken.fromBinder(
+ entry.getKey()).getContainer();
+ sanitizeAndApplyConfigChange(cc, entry.getValue());
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
@Override
public boolean releaseActivityInstance(IBinder token) {
synchronized (mGlobalLock) {
@@ -4446,7 +4480,7 @@
Slog.w(TAG, "cancelTaskWindowTransition: taskId=" + taskId + " not found");
return;
}
- task.cancelWindowTransition();
+ task.cancelTaskWindowTransition();
}
} finally {
Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index c1143c8..cd7c216 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -219,7 +219,7 @@
private int mNextAppTransitionExit;
private int mNextAppTransitionInPlace;
- // Keyed by task id.
+ // Keyed by WindowContainer hashCode.
private final SparseArray<AppTransitionAnimationSpec> mNextAppTransitionAnimationsSpecs
= new SparseArray<>();
private IAppTransitionAnimationSpecsFuture mNextAppTransitionAnimationsSpecsFuture;
@@ -372,8 +372,9 @@
setAppTransitionState(APP_STATE_TIMEOUT);
}
- GraphicBuffer getAppTransitionThumbnailHeader(int taskId) {
- AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(taskId);
+ GraphicBuffer getAppTransitionThumbnailHeader(WindowContainer container) {
+ AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(
+ container.hashCode());
if (spec == null) {
spec = mDefaultNextAppTransitionAnimationSpec;
}
@@ -789,14 +790,15 @@
}
}
- void getNextAppTransitionStartRect(int taskId, Rect rect) {
- AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(taskId);
+ void getNextAppTransitionStartRect(WindowContainer container, Rect rect) {
+ AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(
+ container.hashCode());
if (spec == null) {
spec = mDefaultNextAppTransitionAnimationSpec;
}
if (spec == null || spec.rect == null) {
- Slog.e(TAG, "Starting rect for task: " + taskId + " requested, but not available",
- new Throwable());
+ Slog.e(TAG, "Starting rect for container: " + container
+ + " requested, but not available", new Throwable());
rect.setEmpty();
} else {
rect.set(spec.rect);
@@ -1065,7 +1067,7 @@
* when a thumbnail is specified with the pending animation override.
*/
Animation createThumbnailAspectScaleAnimationLocked(Rect appRect, @Nullable Rect contentInsets,
- GraphicBuffer thumbnailHeader, final int taskId, int uiMode, int orientation) {
+ GraphicBuffer thumbnailHeader, WindowContainer container, int uiMode, int orientation) {
Animation a;
final int thumbWidthI = thumbnailHeader.getWidth();
final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
@@ -1073,7 +1075,7 @@
final int appWidth = appRect.width();
float scaleW = appWidth / thumbWidth;
- getNextAppTransitionStartRect(taskId, mTmpRect);
+ getNextAppTransitionStartRect(container, mTmpRect);
final float fromX;
float fromY;
final float toX;
@@ -1226,7 +1228,7 @@
Animation createAspectScaledThumbnailEnterExitAnimationLocked(int thumbTransitState,
int uiMode, int orientation, int transit, Rect containingFrame, Rect contentInsets,
@Nullable Rect surfaceInsets, @Nullable Rect stableInsets, boolean freeform,
- int taskId) {
+ WindowContainer container) {
Animation a;
final int appWidth = containingFrame.width();
final int appHeight = containingFrame.height();
@@ -1244,10 +1246,10 @@
final boolean scaleUp = thumbTransitState == THUMBNAIL_TRANSITION_ENTER_SCALE_UP;
if (freeform && scaleUp) {
a = createAspectScaledThumbnailEnterFreeformAnimationLocked(
- containingFrame, surfaceInsets, taskId);
+ containingFrame, surfaceInsets, container);
} else if (freeform) {
a = createAspectScaledThumbnailExitFreeformAnimationLocked(
- containingFrame, surfaceInsets, taskId);
+ containingFrame, surfaceInsets, container);
} else {
AnimationSet set = new AnimationSet(true);
@@ -1359,15 +1361,15 @@
}
private Animation createAspectScaledThumbnailEnterFreeformAnimationLocked(Rect frame,
- @Nullable Rect surfaceInsets, int taskId) {
- getNextAppTransitionStartRect(taskId, mTmpRect);
+ @Nullable Rect surfaceInsets, WindowContainer container) {
+ getNextAppTransitionStartRect(container, mTmpRect);
return createAspectScaledThumbnailFreeformAnimationLocked(mTmpRect, frame, surfaceInsets,
true);
}
private Animation createAspectScaledThumbnailExitFreeformAnimationLocked(Rect frame,
- @Nullable Rect surfaceInsets, int taskId) {
- getNextAppTransitionStartRect(taskId, mTmpRect);
+ @Nullable Rect surfaceInsets, WindowContainer container) {
+ getNextAppTransitionStartRect(container, mTmpRect);
return createAspectScaledThumbnailFreeformAnimationLocked(frame, mTmpRect, surfaceInsets,
false);
}
@@ -1469,10 +1471,10 @@
* leaving, and the activity that is entering.
*/
Animation createThumbnailEnterExitAnimationLocked(int thumbTransitState, Rect containingFrame,
- int transit, int taskId) {
+ int transit, WindowContainer container) {
final int appWidth = containingFrame.width();
final int appHeight = containingFrame.height();
- final GraphicBuffer thumbnailHeader = getAppTransitionThumbnailHeader(taskId);
+ final GraphicBuffer thumbnailHeader = getAppTransitionThumbnailHeader(container);
Animation a;
getDefaultNextAppTransitionStartRect(mTmpRect);
final int thumbWidthI = thumbnailHeader != null ? thumbnailHeader.getWidth() : appWidth;
@@ -1615,7 +1617,7 @@
Animation loadAnimation(LayoutParams lp, int transit, boolean enter, int uiMode,
int orientation, Rect frame, Rect displayFrame, Rect insets,
@Nullable Rect surfaceInsets, @Nullable Rect stableInsets, boolean isVoiceInteraction,
- boolean freeform, int taskId) {
+ boolean freeform, WindowContainer container) {
Animation a;
if (isKeyguardGoingAwayTransit(transit) && enter) {
a = loadKeyguardExitAnimation(transit);
@@ -1679,7 +1681,7 @@
mNextAppTransitionScaleUp =
(mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter),
- frame, transit, taskId);
+ frame, transit, container);
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
"applyAnimation: anim=%s nextAppTransition=%s transit=%s isEntrance=%b "
+ "Callers=%s",
@@ -1692,7 +1694,7 @@
(mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP);
a = createAspectScaledThumbnailEnterExitAnimationLocked(
getThumbnailTransitionState(enter), uiMode, orientation, transit, frame,
- insets, surfaceInsets, stableInsets, freeform, taskId);
+ insets, surfaceInsets, stableInsets, freeform, container);
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
"applyAnimation: anim=%s nextAppTransition=%s transit=%s isEntrance=%b "
+ "Callers=%s",
@@ -1895,7 +1897,11 @@
for (int i = 0; i < specs.length; i++) {
AppTransitionAnimationSpec spec = specs[i];
if (spec != null) {
- mNextAppTransitionAnimationsSpecs.put(spec.taskId, spec);
+ final WindowContainer container = findTask(spec.taskId);
+ if (container == null) {
+ continue;
+ }
+ mNextAppTransitionAnimationsSpecs.put(container.hashCode(), spec);
if (i == 0) {
// In full screen mode, the transition code depends on the default spec
// to be set.
@@ -1912,6 +1918,21 @@
}
}
+ private Task findTask(int taskId) {
+ if (taskId < 0) {
+ return null;
+ }
+ final ArrayList<Task> tasks = new ArrayList<>();
+ mDisplayContent.forAllTasks(task -> {
+ if (task.mTaskId == taskId) {
+ tasks.add(task);
+ return true;
+ }
+ return false;
+ });
+ return tasks.size() == 1 ? tasks.get(0) : null;
+ }
+
void overridePendingAppTransitionMultiThumbFuture(
IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback callback,
boolean scaleUp) {
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 3bda0c2..bef6af3 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -410,7 +410,7 @@
ActivityRecord activity = apps.valueAt(i);
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Now changing app %s", activity);
activity.cancelAnimationOnly();
- activity.applyAnimationLocked(null, transit, true, false);
+ activity.applyAnimation(null, transit, true, false);
activity.updateReportedVisibilityLocked();
mService.openSurfaceTransaction();
try {
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java
index 70d5ab9..30f3bc5 100644
--- a/services/core/java/com/android/server/wm/ConfigurationContainer.java
+++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java
@@ -39,11 +39,15 @@
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
+import android.os.IBinder;
import android.util.proto.ProtoOutputStream;
+import android.view.IWindowContainer;
+import android.view.SurfaceControl;
import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
/**
@@ -102,6 +106,11 @@
// Return value from {@link setBounds} indicating the size of the override bounds changed.
static final int BOUNDS_CHANGE_SIZE = 1 << 1;
+ /**
+ * Used as a unique, cross-process identifier for this Container. It also serves a minimal
+ * interface to other processes.
+ */
+ RemoteToken mRemoteToken = null;
/**
* Returns full configuration applied to this configuration container.
@@ -125,9 +134,9 @@
onConfigurationChanged(newParentConfig, true /*forwardToChildren*/);
}
- // TODO: Consolidate with onConfigurationChanged() method above once unification is done. This
- // is only currently need during the process of unification where we don't want configuration
- // forwarded to a child from both parents.
+ // TODO(root-unify): Consolidate with onConfigurationChanged() method above once unification is
+ // done. This is only currently need during the process of unification where we don't want
+ // configuration forwarded to a child from both parents.
public void onConfigurationChanged(Configuration newParentConfig, boolean forwardToChildren) {
mResolvedTmpConfig.setTo(mResolvedOverrideConfiguration);
resolveOverrideConfiguration(newParentConfig);
@@ -634,4 +643,37 @@
abstract protected E getChildAt(int index);
abstract protected ConfigurationContainer getParent();
+
+ // TODO: Consider moving to WindowContainer once hierarchies and Task/Stack are merged.
+ static class RemoteToken extends IWindowContainer.Stub {
+ final WeakReference<ConfigurationContainer> mWeakRef;
+
+ RemoteToken(ConfigurationContainer container) {
+ mWeakRef = new WeakReference<>(container);
+ }
+
+ ConfigurationContainer getContainer() {
+ return mWeakRef.get();
+ }
+
+ static RemoteToken fromBinder(IBinder binder) {
+ return (RemoteToken) binder;
+ }
+
+ @Override
+ public SurfaceControl getLeash() {
+ throw new RuntimeException("Not implemented");
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("RemoteToken{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(' ');
+ sb.append(mWeakRef.get());
+ sb.append('}');
+ return sb.toString();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 2d1d297..d1d468b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -106,6 +106,8 @@
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
@@ -2363,7 +2365,7 @@
@Override
void removeIfPossible() {
- if (isAnimating()) {
+ if (isAnimating(TRANSITION | PARENTS)) {
mDeferredRemoval = true;
return;
}
@@ -2407,7 +2409,19 @@
/** Returns true if a removal action is still being deferred. */
@Override
boolean checkCompleteDeferredRemoval() {
- final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval();
+ boolean stillDeferringRemoval = false;
+
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayChildWindowContainer child = getChildAt(i);
+ stillDeferringRemoval |= child.checkCompleteDeferredRemoval();
+ if (getChildCount() == 0) {
+ // If this display is pending to be removed because it contains an activity with
+ // {@link ActivityRecord#mIsExiting} is true, this display may be removed when
+ // completing the removal of the last activity from
+ // {@link ActivityRecord#checkCompleteDeferredRemoval}.
+ return false;
+ }
+ }
if (!stillDeferringRemoval && mDeferredRemoval) {
removeImmediately();
@@ -3165,13 +3179,15 @@
// to look at all windows below the current target that are in this app, finding the
// highest visible one in layering.
WindowState highestTarget = null;
- if (activity.isSelfAnimating()) {
+ if (activity.isAnimating(TRANSITION)) {
highestTarget = activity.getHighestAnimLayerWindow(curTarget);
}
if (highestTarget != null) {
- if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, mAppTransition + " " + highestTarget
- + " animating=" + highestTarget.isAnimating());
+ if (DEBUG_INPUT_METHOD) {
+ Slog.v(TAG_WM, mAppTransition + " " + highestTarget + " animating="
+ + highestTarget.isAnimating(TRANSITION | PARENTS));
+ }
if (mAppTransition.isTransitionSet()) {
// If we are currently setting up for an animation, hold everything until we
@@ -4322,7 +4338,7 @@
// The split screen divider anchor is located above the split screen window.
layerForSplitScreenDividerAnchor = layer++;
}
- if (s.isTaskAnimating() || s.isAppAnimating()) {
+ if (s.isTaskAnimating() || s.isAppTransitioning()) {
// The animation layer is located above the highest animating stack and no
// higher.
layerForAnimationLayer = layer++;
@@ -4651,7 +4667,8 @@
// so it get's layered above the starting window.
if (imeTarget != null
&& !(imeTarget.mActivityRecord != null && imeTarget.mActivityRecord.hasStartingWindow())
- && (!(imeTarget.inSplitScreenWindowingMode() || imeTarget.mToken.isAppAnimating())
+ && (!(imeTarget.inSplitScreenWindowingMode()
+ || imeTarget.mToken.isAppTransitioning())
&& (imeTarget.getSurfaceControl() != null))) {
mImeWindowsContainers.assignRelativeLayer(t, imeTarget.getSurfaceControl(),
// TODO: We need to use an extra level on the app surface to ensure
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index a783ee9..fcfd9de 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -144,13 +144,16 @@
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
+import android.view.InsetsFlags;
import android.view.InsetsState;
+import android.view.InsetsState.InternalInsetType;
import android.view.MotionEvent;
import android.view.PointerIcon;
import android.view.Surface;
import android.view.View;
import android.view.ViewRootImpl;
import android.view.WindowInsets;
+import android.view.WindowInsetsController.Appearance;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerGlobal;
@@ -332,8 +335,6 @@
private int mResettingSystemUiFlags = 0;
// Bits that we are currently always keeping cleared.
private int mForceClearedSystemUiFlags = 0;
- private int mLastFullscreenStackSysUiFlags;
- private int mLastDockedStackSysUiFlags;
private int mLastAppearance;
private int mLastFullscreenAppearance;
private int mLastDockedAppearance;
@@ -1920,10 +1921,18 @@
vf.set(displayFrames.mStable);
if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
- cf.bottom = displayFrames.mContent.bottom;
+ // cf.bottom should not be below the stable bottom, or the content might be obscured
+ // by the navigation bar.
+ if (cf.bottom > displayFrames.mContent.bottom) {
+ cf.bottom = displayFrames.mContent.bottom;
+ }
} else {
- cf.bottom = displayFrames.mDock.bottom;
- vf.bottom = displayFrames.mContent.bottom;
+ if (cf.bottom > displayFrames.mDock.bottom) {
+ cf.bottom = displayFrames.mDock.bottom;
+ }
+ if (vf.bottom > displayFrames.mContent.bottom) {
+ vf.bottom = displayFrames.mContent.bottom;
+ }
}
} else {
dcf.set(displayFrames.mSystem);
@@ -3164,11 +3173,6 @@
&= ~PolicyControl.adjustClearableFlags(win, View.SYSTEM_UI_CLEARABLE_FLAGS);
}
- final int appearance = win.mAttrs.insetsFlags.appearance;
- final int fullscreenVisibility = updateLightStatusBarLw(0 /* vis */,
- mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
- final int dockedVisibility = updateLightStatusBarLw(0 /* vis */,
- mTopDockedOpaqueWindowState, mTopDockedOpaqueOrDimmingWindowState);
final int fullscreenAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
mTopFullscreenOpaqueWindowState, mTopFullscreenOpaqueOrDimmingWindowState);
final int dockedAppearance = updateLightStatusBarAppearanceLw(0 /* vis */,
@@ -3182,9 +3186,9 @@
final Pair<Integer, Boolean> result =
updateSystemBarsLw(win, mLastSystemUiFlags, tmpVisibility);
final int visibility = result.first;
+ final int appearance = win.mAttrs.insetsFlags.appearance
+ | InsetsFlags.getAppearance(visibility);
final int diff = visibility ^ mLastSystemUiFlags;
- final int fullscreenDiff = fullscreenVisibility ^ mLastFullscreenStackSysUiFlags;
- final int dockedDiff = dockedVisibility ^ mLastDockedStackSysUiFlags;
final InsetsPolicy insetsPolicy = getInsetsPolicy();
final boolean isFullscreen = (visibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)) != 0
@@ -3197,7 +3201,7 @@
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)) != 0
|| behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE
|| behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
- if (diff == 0 && fullscreenDiff == 0 && dockedDiff == 0
+ if (diff == 0
&& mLastAppearance == appearance
&& mLastFullscreenAppearance == fullscreenAppearance
&& mLastDockedAppearance == dockedAppearance
@@ -3208,9 +3212,12 @@
&& mLastDockedStackBounds.equals(mDockedStackBounds)) {
return 0;
}
+
+ // Obtains which types should show transient and which types should abort transient.
+ // If there is no transient state change, this pair will contain two empty arrays.
+ final Pair<int[], int[]> transientState = getTransientState(visibility, mLastSystemUiFlags);
+
mLastSystemUiFlags = visibility;
- mLastFullscreenStackSysUiFlags = fullscreenVisibility;
- mLastDockedStackSysUiFlags = dockedVisibility;
mLastAppearance = appearance;
mLastFullscreenAppearance = fullscreenAppearance;
mLastDockedAppearance = dockedAppearance;
@@ -3232,14 +3239,16 @@
StatusBarManagerInternal statusBar = getStatusBarManagerInternal();
if (statusBar != null) {
final int displayId = getDisplayId();
- // TODO(b/118118435): disabled flags only
- statusBar.setSystemUiVisibility(displayId, visibility, fullscreenVisibility,
- dockedVisibility, 0xffffffff, fullscreenStackBounds,
- dockedStackBounds, isNavbarColorManagedByIme, win.toString());
- if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL) {
- statusBar.onSystemBarAppearanceChanged(displayId, appearance,
- appearanceRegions, isNavbarColorManagedByIme);
+ statusBar.setDisableFlags(displayId, visibility & StatusBarManager.DISABLE_MASK,
+ win.toString());
+ if (transientState.first.length > 0) {
+ statusBar.showTransient(displayId, transientState.first);
}
+ if (transientState.second.length > 0) {
+ statusBar.abortTransient(displayId, transientState.second);
+ }
+ statusBar.onSystemBarAppearanceChanged(displayId, appearance,
+ appearanceRegions, isNavbarColorManagedByIme);
statusBar.topAppWindowChanged(displayId, isFullscreen, isImmersive);
// TODO(b/118118435): Remove this after removing system UI visibilities.
@@ -3250,23 +3259,28 @@
return diff;
}
- private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
- final boolean onKeyguard = isStatusBarKeyguard() && !isKeyguardOccluded();
- final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming;
- if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) {
- // If the top fullscreen-or-dimming window is also the top fullscreen, respect
- // its light flag.
- vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
- & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- } else if (statusColorWin != null && statusColorWin.isDimming()) {
- // Otherwise if it's dimming, clear the light flag.
- vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- }
- return vis;
+ private static Pair<int[], int[]> getTransientState(int vis, int oldVis) {
+ final IntArray typesToShow = new IntArray(0);
+ final IntArray typesToAbort = new IntArray(0);
+ updateTransientState(vis, oldVis, View.STATUS_BAR_TRANSIENT, TYPE_TOP_BAR, typesToShow,
+ typesToAbort);
+ updateTransientState(vis, oldVis, View.NAVIGATION_BAR_TRANSIENT,
+ InsetsState.TYPE_NAVIGATION_BAR, typesToShow, typesToAbort);
+ return Pair.create(typesToShow.toArray(), typesToAbort.toArray());
}
- private int updateLightStatusBarAppearanceLw(int appearance, WindowState opaque,
+ private static void updateTransientState(int vis, int oldVis, int transientFlag,
+ @InternalInsetType int type, IntArray typesToShow, IntArray typesToAbort) {
+ final boolean wasTransient = (oldVis & transientFlag) != 0;
+ final boolean isTransient = (vis & transientFlag) != 0;
+ if (!wasTransient && isTransient) {
+ typesToShow.add(type);
+ } else if (wasTransient && !isTransient) {
+ typesToAbort.add(type);
+ }
+ }
+
+ private int updateLightStatusBarAppearanceLw(@Appearance int appearance, WindowState opaque,
WindowState opaqueOrDimming) {
final boolean onKeyguard = isStatusBarKeyguard() && !isKeyguardOccluded();
final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming;
@@ -3274,7 +3288,10 @@
// If the top fullscreen-or-dimming window is also the top fullscreen, respect
// its light flag.
appearance &= ~APPEARANCE_LIGHT_TOP_BAR;
- appearance |= statusColorWin.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_TOP_BAR;
+ final int legacyAppearance = InsetsFlags.getAppearance(
+ PolicyControl.getSystemUiVisibility(statusColorWin, null));
+ appearance |= (statusColorWin.mAttrs.insetsFlags.appearance | legacyAppearance)
+ & APPEARANCE_LIGHT_TOP_BAR;
} else if (statusColorWin != null && statusColorWin.isDimming()) {
// Otherwise if it's dimming, clear the light flag.
appearance &= ~APPEARANCE_LIGHT_TOP_BAR;
diff --git a/services/core/java/com/android/server/wm/InputManagerCallback.java b/services/core/java/com/android/server/wm/InputManagerCallback.java
index 7f9e76b..1ebbb02 100644
--- a/services/core/java/com/android/server/wm/InputManagerCallback.java
+++ b/services/core/java/com/android/server/wm/InputManagerCallback.java
@@ -4,6 +4,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+import static com.android.server.wm.ActivityRecord.INVALID_PID;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -14,6 +15,7 @@
import android.os.RemoteException;
import android.util.Slog;
import android.view.IWindow;
+import android.view.InputApplicationHandle;
import android.view.KeyEvent;
import android.view.WindowManager;
@@ -80,7 +82,8 @@
* Called by the InputManager.
*/
@Override
- public long notifyANR(IBinder token, String reason) {
+ public long notifyANR(InputApplicationHandle inputApplicationHandle,
+ IBinder token, String reason) {
ActivityRecord activity = null;
WindowState windowState = null;
boolean aboveSystem = false;
@@ -93,6 +96,10 @@
}
}
+ if (activity == null && inputApplicationHandle != null) {
+ activity = ActivityRecord.forTokenLocked(inputApplicationHandle.token);
+ }
+
if (windowState != null) {
Slog.i(TAG_WM, "Input event dispatching timed out "
+ "sending to " + windowState.mAttrs.getTitle()
@@ -122,7 +129,7 @@
// Notify the activity manager about the timeout and let it decide whether
// to abort dispatching or keep waiting.
final boolean abort = activity.keyDispatchingTimedOut(reason,
- windowState.mSession.mPid);
+ (windowState != null) ? windowState.mSession.mPid : INVALID_PID);
if (!abort) {
// The activity manager declined to abort dispatching.
// Wait a bit longer and timeout again later.
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 2e6df60..6cb1e76 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -291,9 +291,12 @@
* onTaskStackBoundsChanged() to be called. But we still should update our known display info
* with the new state so that we can update SystemUI.
*/
- synchronized void onDisplayInfoChanged(DisplayInfo displayInfo) {
- setDisplayInfo(displayInfo);
- notifyMovementBoundsChanged(false /* fromImeAdjustment */, false /* fromShelfAdjustment */);
+ void onDisplayInfoChanged(DisplayInfo displayInfo) {
+ synchronized (mService.mGlobalLock) {
+ setDisplayInfo(displayInfo);
+ notifyMovementBoundsChanged(false /* fromImeAdjustment */,
+ false /* fromShelfAdjustment */);
+ }
}
/**
diff --git a/services/core/java/com/android/server/wm/PolicyControl.java b/services/core/java/com/android/server/wm/PolicyControl.java
index 4c8ce9e..0f92bc8 100644
--- a/services/core/java/com/android/server/wm/PolicyControl.java
+++ b/services/core/java/com/android/server/wm/PolicyControl.java
@@ -26,6 +26,8 @@
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -51,7 +53,8 @@
private static final String TAG = "PolicyControl";
private static final boolean DEBUG = false;
- private static final String NAME_IMMERSIVE_FULL = "immersive.full";
+ @VisibleForTesting
+ static final String NAME_IMMERSIVE_FULL = "immersive.full";
private static final String NAME_IMMERSIVE_STATUS = "immersive.status";
private static final String NAME_IMMERSIVE_NAVIGATION = "immersive.navigation";
private static final String NAME_IMMERSIVE_PRECONFIRMATIONS = "immersive.preconfirms";
@@ -67,15 +70,19 @@
: (attrs.systemUiVisibility | attrs.subtreeSystemUiVisibility);
if (sImmersiveStatusFilter != null && sImmersiveStatusFilter.matches(attrs)) {
vis |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- | View.SYSTEM_UI_FLAG_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ | View.SYSTEM_UI_FLAG_FULLSCREEN;
+ if (attrs.isFullscreen()) {
+ vis |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+ }
vis &= ~(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.STATUS_BAR_TRANSLUCENT);
}
if (sImmersiveNavigationFilter != null && sImmersiveNavigationFilter.matches(attrs)) {
vis |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+ if (attrs.isFullscreen()) {
+ vis |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+ }
vis &= ~(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.NAVIGATION_BAR_TRANSLUCENT);
}
@@ -144,7 +151,8 @@
}
}
- private static void setFilters(String value) {
+ @VisibleForTesting
+ static void setFilters(String value) {
if (DEBUG) Slog.d(TAG, "setFilters: " + value);
sImmersiveStatusFilter = null;
sImmersiveNavigationFilter = null;
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 2dae126..01cbc5d 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -211,9 +211,9 @@
// If there are multiple tasks in the target stack (ie. the home stack, with 3p
// and default launchers coexisting), then move the task to the top as a part of
// moving the stack to the front
- if (targetStack.topTask() != targetActivity.getTaskRecord()) {
- targetStack.addTask(targetActivity.getTaskRecord(), true /* toTop */,
- "startRecentsActivity");
+ final TaskRecord task = targetActivity.getTaskRecord();
+ if (targetStack.topTask() != task) {
+ targetStack.insertTaskAtTop(task, targetActivity);
}
} else {
// No recents activity, create the new recents activity bottom most
diff --git a/services/core/java/com/android/server/wm/RefreshRatePolicy.java b/services/core/java/com/android/server/wm/RefreshRatePolicy.java
index 0c0cf92..e0a7b18 100644
--- a/services/core/java/com/android/server/wm/RefreshRatePolicy.java
+++ b/services/core/java/com/android/server/wm/RefreshRatePolicy.java
@@ -16,6 +16,9 @@
package com.android.server.wm;
+import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
+
import android.util.ArraySet;
import android.view.Display.Mode;
import android.view.DisplayInfo;
@@ -67,7 +70,7 @@
// If app is animating, it's not able to control refresh rate because we want the animation
// to run in default refresh rate.
- if (w.isAnimating()) {
+ if (w.isAnimating(TRANSITION | PARENTS)) {
return 0;
}
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index c23ffd9..efd1241 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -41,7 +41,6 @@
import com.android.server.protolog.ProtoLogImpl;
import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
-import com.android.server.wm.utils.InsetUtils;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -76,20 +75,20 @@
}
/**
- * Creates an animation record for each individual {@link ActivityRecord}.
+ * Creates an animation record for each individual {@link WindowContainer}.
*
- * @param activity The app to animate.
+ * @param windowContainer The windows to animate.
* @param position The position app bounds, in screen coordinates.
* @param stackBounds The stack bounds of the app relative to position.
* @param startBounds The stack bounds before the transition, in screen coordinates
* @return The record representing animation(s) to run on the app.
*/
- RemoteAnimationRecord createRemoteAnimationRecord(ActivityRecord activity, Point position,
- Rect stackBounds, Rect startBounds) {
- ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "createAnimationAdapter(): token=%s",
- activity);
+ RemoteAnimationRecord createRemoteAnimationRecord(WindowContainer windowContainer,
+ Point position, Rect stackBounds, Rect startBounds) {
+ ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "createAnimationAdapter(): container=%s",
+ windowContainer);
final RemoteAnimationRecord adapters =
- new RemoteAnimationRecord(activity, position, stackBounds, startBounds);
+ new RemoteAnimationRecord(windowContainer, position, stackBounds, startBounds);
mPendingAnimations.add(adapters);
return adapters;
}
@@ -169,11 +168,12 @@
final RemoteAnimationRecord wrappers = mPendingAnimations.get(i);
final RemoteAnimationTarget target = wrappers.createRemoteAnimationTarget();
if (target != null) {
- ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tAdd token=%s", wrappers.mActivityRecord);
+ ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tAdd container=%s",
+ wrappers.mWindowContainer);
targets.add(target);
} else {
- ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tRemove token=%s",
- wrappers.mActivityRecord);
+ ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tRemove container=%s",
+ wrappers.mWindowContainer);
// We can't really start an animation but we still need to make sure to finish the
// pending animation that was started by SurfaceAnimator
@@ -228,7 +228,8 @@
.onAnimationFinished(adapters.mThumbnailAdapter);
}
mPendingAnimations.remove(i);
- ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tapp=%s", adapters.mActivityRecord);
+ ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "\tcontainer=%s",
+ adapters.mWindowContainer);
}
for (int i = mPendingWallpaperAnimations.size() - 1; i >= 0; i--) {
@@ -332,7 +333,7 @@
};
/**
- * Contains information about a remote-animation for one AppWindowToken. This keeps track of,
+ * Contains information about a remote-animation for one WindowContainer. This keeps track of,
* potentially, multiple animating surfaces (AdapterWrappers) associated with one
* Window/Transition. For example, a change transition has an adapter controller for the
* main window and an adapter controlling the start-state snapshot.
@@ -345,12 +346,12 @@
RemoteAnimationAdapterWrapper mAdapter;
RemoteAnimationAdapterWrapper mThumbnailAdapter = null;
RemoteAnimationTarget mTarget;
- final ActivityRecord mActivityRecord;
+ final WindowContainer mWindowContainer;
final Rect mStartBounds;
- RemoteAnimationRecord(ActivityRecord activityRecord, Point endPos, Rect endBounds,
+ RemoteAnimationRecord(WindowContainer windowContainer, Point endPos, Rect endBounds,
Rect startBounds) {
- mActivityRecord = activityRecord;
+ mWindowContainer = windowContainer;
mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, endBounds);
if (startBounds != null) {
mStartBounds = new Rect(startBounds);
@@ -366,31 +367,20 @@
}
RemoteAnimationTarget createRemoteAnimationTarget() {
- final Task task = mActivityRecord.getTask();
- final WindowState mainWindow = mActivityRecord.findMainWindow();
- if (task == null || mainWindow == null || mAdapter == null
+ if (mAdapter == null
|| mAdapter.mCapturedFinishCallback == null
|| mAdapter.mCapturedLeash == null) {
return null;
}
- final Rect insets = new Rect();
- mainWindow.getContentInsets(insets);
- InsetUtils.addInsets(insets, mActivityRecord.getLetterboxInsets());
- mTarget = new RemoteAnimationTarget(task.mTaskId, getMode(),
- mAdapter.mCapturedLeash, !mActivityRecord.fillsParent(),
- mainWindow.mWinAnimator.mLastClipRect, insets,
- mActivityRecord.getPrefixOrderIndex(), mAdapter.mPosition,
- mAdapter.mStackBounds, task.getWindowConfiguration(), false /*isNotInRecents*/,
- mThumbnailAdapter != null ? mThumbnailAdapter.mCapturedLeash : null,
- mStartBounds);
+ mTarget = mWindowContainer.createRemoteAnimationTarget(this);
return mTarget;
}
- private int getMode() {
- final DisplayContent dc = mActivityRecord.getDisplayContent();
- if (dc.mOpeningApps.contains(mActivityRecord)) {
+ int getMode() {
+ final DisplayContent dc = mWindowContainer.getDisplayContent();
+ if (dc.mOpeningApps.contains(mWindowContainer)) {
return RemoteAnimationTarget.MODE_OPENING;
- } else if (dc.mChangingApps.contains(mActivityRecord)) {
+ } else if (dc.mChangingApps.contains(mWindowContainer)) {
return RemoteAnimationTarget.MODE_CHANGING;
} else {
return RemoteAnimationTarget.MODE_CLOSING;
@@ -398,12 +388,12 @@
}
}
- private class RemoteAnimationAdapterWrapper implements AnimationAdapter {
+ class RemoteAnimationAdapterWrapper implements AnimationAdapter {
private final RemoteAnimationRecord mRecord;
SurfaceControl mCapturedLeash;
private OnAnimationFinishedCallback mCapturedFinishCallback;
- private final Point mPosition = new Point();
- private final Rect mStackBounds = new Rect();
+ final Point mPosition = new Point();
+ final Rect mStackBounds = new Rect();
RemoteAnimationAdapterWrapper(RemoteAnimationRecord record, Point position,
Rect stackBounds) {
@@ -423,7 +413,7 @@
ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "startAnimation");
// Restore z-layering, position and stack crop until client has a chance to modify it.
- t.setLayer(animationLeash, mRecord.mActivityRecord.getPrefixOrderIndex());
+ t.setLayer(animationLeash, mRecord.mWindowContainer.getPrefixOrderIndex());
if (mRecord.mStartBounds != null) {
t.setPosition(animationLeash, mRecord.mStartBounds.left, mRecord.mStartBounds.top);
t.setWindowCrop(animationLeash, mRecord.mStartBounds.width(),
@@ -464,7 +454,7 @@
@Override
public void dump(PrintWriter pw, String prefix) {
- pw.print(prefix); pw.print("token="); pw.println(mRecord.mActivityRecord);
+ pw.print(prefix); pw.print("container="); pw.println(mRecord.mWindowContainer);
if (mRecord.mTarget != null) {
pw.print(prefix); pw.println("Target:");
mRecord.mTarget.dump(pw, prefix + " ");
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 9db6dc2..2ca929e 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -1154,7 +1154,7 @@
// activity is started and resumed, and no recursion occurs.
final ActivityStack focusedStack = display.getFocusedStack();
if (focusedStack != null) {
- focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
+ result |= focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
}
}
@@ -1265,8 +1265,7 @@
: task.realActivity != null ? task.realActivity.flattenToString()
: task.getTopActivity() != null ? task.getTopActivity().packageName
: "unknown";
- taskBounds[i] = new Rect();
- task.getWindowContainerBounds(taskBounds[i]);
+ taskBounds[i] = mService.getTaskBounds(task.mTaskId);
taskUserIds[i] = task.mUserId;
}
info.taskIds = taskIds;
@@ -1629,7 +1628,7 @@
return false;
}
- <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r,
+ ActivityStack getLaunchStack(@Nullable ActivityRecord r,
@Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop) {
return getLaunchStack(r, options, candidateTask, onTop, null /* launchParams */,
-1 /* no realCallingPid */, -1 /* no realCallingUid */);
@@ -1647,7 +1646,7 @@
*
* @return The stack to use for the launch or INVALID_STACK_ID.
*/
- <T extends ActivityStack> T getLaunchStack(@Nullable ActivityRecord r,
+ ActivityStack getLaunchStack(@Nullable ActivityRecord r,
@Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, boolean onTop,
@Nullable LaunchParamsController.LaunchParams launchParams, int realCallingPid,
int realCallingUid) {
@@ -1675,7 +1674,7 @@
}
final int activityType = resolveActivityType(r, options, candidateTask);
- T stack;
+ ActivityStack stack;
// Next preference for stack goes to the display Id set the candidate display.
if (launchParams != null && launchParams.mPreferredDisplayId != INVALID_DISPLAY) {
@@ -1691,7 +1690,7 @@
if (displayId != INVALID_DISPLAY && (canLaunchOnDisplay(r, displayId)
|| canLaunchOnDisplayFromStartRequest)) {
if (r != null) {
- stack = (T) getValidLaunchStackOnDisplay(displayId, r, candidateTask, options,
+ stack = getValidLaunchStackOnDisplay(displayId, r, candidateTask, options,
launchParams);
if (stack != null) {
return stack;
@@ -1876,7 +1875,12 @@
ActivityStack getNextFocusableStack(@NonNull ActivityStack currentFocus,
boolean ignoreCurrent) {
// First look for next focusable stack on the same display
- final ActivityDisplay preferredDisplay = currentFocus.getDisplay();
+ ActivityDisplay preferredDisplay = currentFocus.getDisplay();
+ if (preferredDisplay == null) {
+ // Stack is currently detached because it is being removed. Use the previous display it
+ // was on.
+ preferredDisplay = getActivityDisplay(currentFocus.mPrevDisplayId);
+ }
final ActivityStack preferredFocusableStack = preferredDisplay.getNextFocusableStack(
currentFocus, ignoreCurrent);
if (preferredFocusableStack != null) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 17f5abd..149bcfb 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -206,7 +206,7 @@
}
@Override
- void onChildPositionChanged() {
+ void onChildPositionChanged(WindowContainer child) {
mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
!mWmService.mPerDisplayFocusEnabled /* updateInputWindows */);
}
@@ -787,7 +787,7 @@
}
}
- if (curDisplay.mAppTransition.isRunning() && !curDisplay.isAppAnimating()) {
+ if (curDisplay.mAppTransition.isRunning() && !curDisplay.isAppTransitioning()) {
// We have finished the animation of an app transition. To do this, we have
// delayed a lot of operations like showing and hiding apps, moving apps in
// Z-order, etc.
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index bf7dd57..183ca07 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
@@ -24,17 +25,19 @@
import static android.content.res.Configuration.EMPTY;
import static android.view.SurfaceControl.METADATA_TASK_ID;
+import static com.android.server.EventLogTags.WM_TASK_CREATED;
import static com.android.server.EventLogTags.WM_TASK_REMOVED;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.TaskProto.APP_WINDOW_TOKENS;
import static com.android.server.wm.TaskProto.BOUNDS;
-import static com.android.server.wm.TaskProto.DEFER_REMOVAL;
import static com.android.server.wm.TaskProto.DISPLAYED_BOUNDS;
import static com.android.server.wm.TaskProto.FILLS_PARENT;
import static com.android.server.wm.TaskProto.ID;
import static com.android.server.wm.TaskProto.SURFACE_HEIGHT;
import static com.android.server.wm.TaskProto.SURFACE_WIDTH;
import static com.android.server.wm.TaskProto.WINDOW_CONTAINER;
+import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -50,10 +53,12 @@
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
+import android.view.RemoteAnimationTarget;
import android.view.Surface;
import android.view.SurfaceControl;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ToBooleanFunction;
import java.io.PrintWriter;
import java.util.function.Consumer;
@@ -61,17 +66,19 @@
class Task extends WindowContainer<ActivityRecord> implements ConfigurationContainerListener{
static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_WM;
- // TODO: Track parent marks like this in WindowContainer.
- TaskStack mStack;
+ final ActivityTaskManagerService mAtmService;
+
/* Unique identifier for this task. */
final int mTaskId;
/* User for which this task was created. */
- final int mUserId;
+ // TODO: Make final
+ int mUserId;
final Rect mPreparedFrozenBounds = new Rect();
final Configuration mPreparedFrozenMergedConfig = new Configuration();
// If non-empty, bounds used to display the task during animations/interactions.
+ // TODO(b/119687367): This member is temporary.
private final Rect mOverrideDisplayedBounds = new Rect();
/** ID of the display which rotation {@link #mRotation} has. */
@@ -88,11 +95,12 @@
private Rect mTmpRect2 = new Rect();
// Resize mode of the task. See {@link ActivityInfo#resizeMode}
- private int mResizeMode;
+ // Based on the {@link ActivityInfo#resizeMode} of the root activity.
+ int mResizeMode;
- // Whether the task supports picture-in-picture.
- // See {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE}
- private boolean mSupportsPictureInPicture;
+ // Whether or not this task and its activities support PiP. Based on the
+ // {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag of the root activity.
+ boolean mSupportsPictureInPicture;
// Whether the task is currently being drag-resized
private boolean mDragResizing;
@@ -114,78 +122,67 @@
/** @see #setCanAffectSystemUiFlags */
private boolean mCanAffectSystemUiFlags = true;
- // TODO: remove after unification
- TaskRecord mTaskRecord;
-
- // TODO: Remove after unification.
- @Override
- public void onConfigurationChanged(Configuration newParentConfig, boolean forwardToChildren) {
- // Forward configuration changes in cases
- // - children won't get it from TaskRecord
- // - it's a pinned task
- forwardToChildren &= (mTaskRecord == null) || inPinnedWindowingMode();
- super.onConfigurationChanged(newParentConfig, forwardToChildren);
- }
-
- Task(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode,
- boolean supportsPictureInPicture, TaskDescription taskDescription,
- TaskRecord taskRecord) {
- super(service);
+ Task(int taskId, TaskStack stack, int userId, int resizeMode, boolean supportsPictureInPicture,
+ TaskDescription taskDescription, ActivityTaskManagerService atm) {
+ super(atm.mWindowManager);
+ mAtmService = atm;
mTaskId = taskId;
- mStack = stack;
mUserId = userId;
mResizeMode = resizeMode;
mSupportsPictureInPicture = supportsPictureInPicture;
- mTaskRecord = taskRecord;
mTaskDescription = taskDescription;
+ EventLog.writeEvent(WM_TASK_CREATED, mTaskId,
+ stack != null ? stack.mStackId : INVALID_STACK_ID);
// Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
setOrientation(SCREEN_ORIENTATION_UNSET);
- if (mTaskRecord != null) {
- // This can be null when we call createTaskInStack in WindowTestUtils. Remove this after
- // unification.
- mTaskRecord.registerConfigurationChangeListener(this);
- } else {
- setBounds(getResolvedOverrideBounds());
- }
+ // TODO(task-merge): Is this really needed?
+ //setBounds(getResolvedOverrideBounds());
}
@Override
DisplayContent getDisplayContent() {
- return mStack != null ? mStack.getDisplayContent() : null;
+ return getTaskStack() != null ? getTaskStack().getDisplayContent() : null;
}
- private int getAdjustedAddPosition(int suggestedPosition) {
- final int size = mChildren.size();
- if (suggestedPosition >= size) {
- return Math.min(size, suggestedPosition);
+ TaskStack getTaskStack() {
+ return (TaskStack) getParent();
+ }
+
+ int getAdjustedAddPosition(ActivityRecord r, int suggestedPosition) {
+ int maxPosition = mChildren.size();
+ if (!r.mTaskOverlay) {
+ // We want to place all non-overlay activities below overlays.
+ while (maxPosition > 0) {
+ final ActivityRecord current = mChildren.get(maxPosition - 1);
+ if (current.mTaskOverlay && !current.removed) {
+ --maxPosition;
+ continue;
+ }
+ break;
+ }
+ if (maxPosition < 0) {
+ maxPosition = 0;
+ }
}
- for (int pos = 0; pos < size && pos < suggestedPosition; ++pos) {
+ if (suggestedPosition >= maxPosition) {
+ return Math.min(maxPosition, suggestedPosition);
+ }
+
+ for (int pos = 0; pos < maxPosition && pos < suggestedPosition; ++pos) {
// TODO: Confirm that this is the behavior we want long term.
if (mChildren.get(pos).removed) {
// suggestedPosition assumes removed tokens are actually gone.
++suggestedPosition;
}
}
- return Math.min(size, suggestedPosition);
- }
-
- @Override
- void addChild(ActivityRecord child, int position) {
- position = getAdjustedAddPosition(position);
- super.addChild(child, position);
-
- // Inform the TaskRecord side of the child addition
- // TODO(task-unify): Will be removed after task unification.
- if (mTaskRecord != null) {
- mTaskRecord.onChildAdded(child, position);
- }
+ return Math.min(maxPosition, suggestedPosition);
}
@Override
void positionChildAt(int position, ActivityRecord child, boolean includingParents) {
- position = getAdjustedAddPosition(position);
+ position = getAdjustedAddPosition(child, position);
super.positionChildAt(position, child, includingParents);
}
@@ -204,7 +201,7 @@
// No reason to defer removal of a Task that doesn't have any child.
return false;
}
- return hasWindowsAlive() && mStack.isSelfOrChildAnimating();
+ return hasWindowsAlive() && getTaskStack().isAnimating(TRANSITION | CHILDREN);
}
@Override
@@ -220,92 +217,40 @@
void removeImmediately() {
if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeTask");
- if (mTaskRecord != null) {
- mTaskRecord.unregisterConfigurationChangeListener(this);
- }
-
super.removeImmediately();
}
- void reparent(TaskStack stack, int position, boolean moveParents) {
- if (stack == mStack) {
- throw new IllegalArgumentException(
- "task=" + this + " already child of stack=" + mStack);
- }
- if (stack == null) {
- throw new IllegalArgumentException("reparent: could not find stack.");
- }
+ // TODO: Consolidate this with TaskRecord.reparent()
+ void reparent(TaskStack stack, int position, boolean moveParents, String reason) {
if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId
- + " from stack=" + mStack);
+ + " from stack=" + getTaskStack());
EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "reParentTask");
- final DisplayContent prevDisplayContent = getDisplayContent();
- // If we are moving from the fullscreen stack to the pinned stack
- // then we want to preserve our insets so that there will not
- // be a jump in the area covered by system decorations. We rely
- // on the pinned animation to later unset this value.
- if (stack.inPinnedWindowingMode()) {
- mPreserveNonFloatingState = true;
- } else {
- mPreserveNonFloatingState = false;
+ final ActivityStack prevStack = getTaskStack().mActivityStack;
+ final boolean wasTopFocusedStack =
+ mAtmService.mRootActivityContainer.isTopDisplayFocusedStack(prevStack);
+ final ActivityDisplay prevStackDisplay = prevStack.getDisplay();
+
+ reparent(stack, position);
+
+ if (!moveParents) {
+ // Only move home stack forward if we are not going to move the new parent forward.
+ prevStack.moveHomeStackToFrontIfNeeded(wasTopFocusedStack, prevStackDisplay, reason);
}
- getParent().removeChild(this);
- stack.addTask(this, position, showForAllUsers(), moveParents);
+ // TODO(task-merge): Remove cast.
+ stack.positionChildAt(position, (TaskRecord) this, moveParents);
- // Relayout display(s).
- final DisplayContent displayContent = stack.getDisplayContent();
- displayContent.setLayoutNeeded();
- if (prevDisplayContent != displayContent) {
- onDisplayChanged(displayContent);
- prevDisplayContent.setLayoutNeeded();
- }
- getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
+ // If we are moving from the fullscreen stack to the pinned stack then we want to preserve
+ // our insets so that there will not be a jump in the area covered by system decorations.
+ // We rely on the pinned animation to later unset this value.
+ mPreserveNonFloatingState = stack.inPinnedWindowingMode();
}
/** @see ActivityTaskManagerService#positionTaskInStack(int, int, int). */
void positionAt(int position) {
- mStack.positionChildAt(position, this, false /* includingParents */);
- }
-
- @Override
- void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- super.onParentChanged(newParent, oldParent);
-
- // Update task bounds if needed.
- adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
-
- if (getWindowConfiguration().windowsAreScaleable()) {
- // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
- // while a resize is pending.
- forceWindowsScaleable(true /* force */);
- } else {
- forceWindowsScaleable(false /* force */);
- }
- }
-
- @Override
- void removeChild(ActivityRecord child) {
- if (!mChildren.contains(child)) {
- Slog.e(TAG, "removeChild: token=" + this + " not found.");
- return;
- }
-
- super.removeChild(child);
-
- // Inform the TaskRecord side of the child removal
- // TODO(task-unify): Will be removed after task unification.
- if (mTaskRecord != null) {
- mTaskRecord.onChildRemoved(child);
- }
-
- // TODO(task-unify): Need to make this account for what we are doing in
- // ActivityRecord.removeFromHistory so that the task isn't removed in some situations when
- // we unify task level.
- if (mChildren.isEmpty()) {
- EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeActivity: last activity");
- removeIfPossible();
- }
+ // TODO(task-merge): Remove cast.
+ getTaskStack().positionChildAt(position, (TaskRecord) this, false /* includingParents */);
}
void setSendingToBottom(boolean toBottom) {
@@ -329,7 +274,8 @@
@Override
public int setBounds(Rect bounds) {
int rotation = Surface.ROTATION_0;
- final DisplayContent displayContent = mStack.getDisplayContent();
+ final DisplayContent displayContent = getTaskStack() != null
+ ? getTaskStack().getDisplayContent() : null;
if (displayContent != null) {
rotation = displayContent.getDisplayInfo().rotation;
} else if (bounds == null) {
@@ -353,9 +299,8 @@
// No one in higher hierarchy handles this request, let's adjust our bounds to fulfill
// it if possible.
- // TODO: Move to TaskRecord after unification is done.
- if (mTaskRecord != null && mTaskRecord.getParent() != null) {
- mTaskRecord.onConfigurationChanged(mTaskRecord.getParent().getConfiguration());
+ if (getParent() != null) {
+ onConfigurationChanged(getParent().getConfiguration());
return true;
}
return false;
@@ -377,8 +322,9 @@
}
/**
- * Sets bounds that override where the task is displayed. Used during transient operations
- * like animation / interaction.
+ * Displayed bounds are used to set where the task is drawn at any given time. This is
+ * separate from its actual bounds so that the app doesn't see any meaningful configuration
+ * changes during transitionary periods.
*/
void setOverrideDisplayedBounds(Rect overrideDisplayedBounds) {
if (overrideDisplayedBounds != null) {
@@ -397,13 +343,13 @@
return mOverrideDisplayedBounds;
}
- void setResizeable(int resizeMode) {
- mResizeMode = resizeMode;
+ boolean isResizeable(boolean checkSupportsPip) {
+ return (mAtmService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
+ || (checkSupportsPip && mSupportsPictureInPicture));
}
boolean isResizeable() {
- return ActivityInfo.isResizeableMode(mResizeMode) || mSupportsPictureInPicture
- || mWmService.mAtmService.mForceResizableActivities;
+ return isResizeable(true /* checkSupportsPip */);
}
/**
@@ -460,6 +406,10 @@
}
}
+ /**
+ * Gets the current overridden displayed bounds. These will be empty if the task is not
+ * currently overriding where it is displayed.
+ */
@Override
public Rect getDisplayedBounds() {
if (mOverrideDisplayedBounds.isEmpty()) {
@@ -469,6 +419,17 @@
}
}
+ @Override
+ void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
+ Rect outSurfaceInsets) {
+ final WindowState windowState = getTopVisibleAppMainWindow();
+ if (windowState != null) {
+ windowState.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
+ } else {
+ super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
+ }
+ }
+
/**
* Calculate the maximum visible area of this task. If the task has only one app,
* the result will be visible frame of that app. If the task has more than one apps,
@@ -505,7 +466,7 @@
/** Bounds of the task to be used for dimming, as well as touch related tests. */
public void getDimBounds(Rect out) {
- final DisplayContent displayContent = mStack.getDisplayContent();
+ final DisplayContent displayContent = getTaskStack().getDisplayContent();
// It doesn't matter if we in particular are part of the resize, since we couldn't have
// a DimLayer anyway if we weren't visible.
final boolean dockedResizing = displayContent != null
@@ -522,9 +483,9 @@
// stack bounds and so we don't even want to use them. Even if the app should not be
// resized the Dim should keep up with the divider.
if (dockedResizing) {
- mStack.getBounds(out);
+ getTaskStack().getBounds(out);
} else {
- mStack.getBounds(mTmpRect);
+ getTaskStack().getBounds(mTmpRect);
mTmpRect.intersect(getBounds());
out.set(mTmpRect);
}
@@ -537,9 +498,9 @@
void setDragResizing(boolean dragResizing, int dragResizeMode) {
if (mDragResizing != dragResizing) {
// No need to check if the mode is allowed if it's leaving dragResize
- if (dragResizing && !DragResizeMode.isModeAllowedForStack(mStack, dragResizeMode)) {
+ if (dragResizing && !DragResizeMode.isModeAllowedForStack(getTaskStack(), dragResizeMode)) {
throw new IllegalArgumentException("Drag resize mode not allow for stack stackId="
- + mStack.mStackId + " dragResizeMode=" + dragResizeMode);
+ + getTaskStack().mStackId + " dragResizeMode=" + dragResizeMode);
}
mDragResizing = dragResizing;
mDragResizeMode = dragResizeMode;
@@ -564,7 +525,7 @@
setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
}
- private void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
+ void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
if (displayContent == null) {
return;
}
@@ -605,9 +566,7 @@
displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
if (setBounds(mTmpRect2) != BOUNDS_CHANGE_NONE) {
- if (mTaskRecord != null) {
- mTaskRecord.requestResize(getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
- }
+ mAtmService.resizeTask(mTaskId, getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
}
}
@@ -631,7 +590,7 @@
*/
boolean isFloating() {
return getWindowConfiguration().tasksAreFloating()
- && !mStack.isAnimatingBoundsToFullscreen() && !mPreserveNonFloatingState;
+ && !getTaskStack().isAnimatingBoundsToFullscreen() && !mPreserveNonFloatingState;
}
@Override
@@ -645,6 +604,18 @@
return getAppAnimationLayer(ANIMATION_LAYER_HOME);
}
+ boolean shouldAnimate() {
+ // Don't animate while the task runs recents animation but only if we are in the mode
+ // where we cancel with deferred screenshot, which means that the controller has
+ // transformed the task.
+ final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
+ if (controller != null && controller.isAnimatingTask(this)
+ && controller.shouldDeferCancelUntilNextTransition()) {
+ return false;
+ }
+ return true;
+ }
+
@Override
SurfaceControl.Builder makeSurface() {
return super.makeSurface().setMetadata(METADATA_TASK_ID, mTaskId);
@@ -660,6 +631,22 @@
return false;
}
+ /**
+ * @return {@code true} if changing app transition is running.
+ */
+ @Override
+ boolean isChangingAppTransition() {
+ final ActivityRecord activity = getTopVisibleActivity();
+ return activity != null && getDisplayContent().mChangingApps.contains(activity);
+ }
+
+ @Override
+ RemoteAnimationTarget createRemoteAnimationTarget(
+ RemoteAnimationController.RemoteAnimationRecord record) {
+ final ActivityRecord activity = getTopVisibleActivity();
+ return activity != null ? activity.createRemoteAnimationTarget(record) : null;
+ }
+
WindowState getTopVisibleAppMainWindow() {
final ActivityRecord activity = getTopVisibleActivity();
return activity != null ? activity.findMainWindow() : null;
@@ -717,7 +704,8 @@
}
void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
- mTaskRecord.onSnapshotChanged(snapshot);
+ mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(
+ mTaskId, snapshot);
}
TaskDescription getTaskDescription() {
@@ -734,6 +722,11 @@
callback.accept(this);
}
+ @Override
+ boolean forAllTasks(ToBooleanFunction<Task> callback) {
+ return callback.apply(this);
+ }
+
/**
* @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI
* flags. See {@link WindowState#canAffectSystemUiFlags()}.
@@ -753,11 +746,6 @@
mDimmer.dontAnimateExit();
}
- @Override
- public String toString() {
- return "{taskId=" + mTaskId + " appTokens=" + mChildren + "}";
- }
-
String getName() {
return toShortString();
}
@@ -784,9 +772,8 @@
}
}
- @CallSuper
- @Override
- public void writeToProto(ProtoOutputStream proto, long fieldId,
+ // TODO(proto-merge): Remove once protos for TaskRecord and Task are merged.
+ void writeToProtoInnerTaskOnly(ProtoOutputStream proto, long fieldId,
@WindowTraceLogLevel int logLevel) {
if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
return;
@@ -802,8 +789,10 @@
proto.write(FILLS_PARENT, matchParentBounds());
getBounds().writeToProto(proto, BOUNDS);
mOverrideDisplayedBounds.writeToProto(proto, DISPLAYED_BOUNDS);
- proto.write(SURFACE_WIDTH, mSurfaceControl.getWidth());
- proto.write(SURFACE_HEIGHT, mSurfaceControl.getHeight());
+ if (mSurfaceControl != null) {
+ proto.write(SURFACE_WIDTH, mSurfaceControl.getWidth());
+ proto.write(SURFACE_HEIGHT, mSurfaceControl.getHeight());
+ }
proto.end(token);
}
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 478b1b5..f7b802d 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -30,6 +30,7 @@
import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.app.IActivityTaskManager;
import android.graphics.Point;
import android.graphics.Rect;
@@ -104,6 +105,7 @@
@VisibleForTesting
Task mTask;
+ WindowState mWindow;
private boolean mResizing;
private boolean mPreserveOrientation;
private boolean mStartOrientationWasLandscape;
@@ -238,8 +240,9 @@
/**
* @param displayContent The Display that the window being dragged is on.
+ * @param win The window which will be dragged.
*/
- void register(DisplayContent displayContent) {
+ void register(DisplayContent displayContent, @NonNull WindowState win) {
final Display display = displayContent.getDisplay();
if (DEBUG_TASK_POSITIONING) {
@@ -309,6 +312,17 @@
display.getRealSize(mMaxVisibleSize);
mDragEnded = false;
+
+ try {
+ mClientCallback = win.mClient.asBinder();
+ mClientCallback.linkToDeath(this, 0 /* flags */);
+ } catch (RemoteException e) {
+ // The caller has died, so clean up TaskPositioningController.
+ mService.mTaskPositioningController.finishTaskPositioning();
+ return;
+ }
+ mWindow = win;
+ mTask = win.getTask();
}
void unregister() {
@@ -341,25 +355,19 @@
ProtoLog.d(WM_DEBUG_ORIENTATION, "Resuming rotation after re-position");
mDisplayContent.getDisplayRotation().resume();
mDisplayContent = null;
- mClientCallback.unlinkToDeath(this, 0 /* flags */);
+ if (mClientCallback != null) {
+ mClientCallback.unlinkToDeath(this, 0 /* flags */);
+ }
+ mWindow = null;
}
- void startDrag(WindowState win, boolean resize, boolean preserveOrientation, float startX,
- float startY) {
+ void startDrag(boolean resize, boolean preserveOrientation, float startX,
+ float startY) {
if (DEBUG_TASK_POSITIONING) {
- Slog.d(TAG, "startDrag: win=" + win + ", resize=" + resize
+ Slog.d(TAG, "startDrag: win=" + mWindow + ", resize=" + resize
+ ", preserveOrientation=" + preserveOrientation + ", {" + startX + ", "
+ startY + "}");
}
- try {
- mClientCallback = win.mClient.asBinder();
- mClientCallback.linkToDeath(this, 0 /* flags */);
- } catch (RemoteException e) {
- // The caller has died, so clean up TaskPositioningController.
- mService.mTaskPositioningController.finishTaskPositioning();
- return;
- }
- mTask = win.getTask();
// Use the bounds of the task which accounts for
// multiple app windows. Don't use any bounds from win itself as it
// may not be the same size as the task.
@@ -441,7 +449,7 @@
}
// This is a moving or scrolling operation.
- mTask.mStack.getDimBounds(mTmpRect);
+ mTask.getTaskStack().getDimBounds(mTmpRect);
// If a target window is covered by system bar, there is no way to move it again by touch.
// So we exclude them from stack bounds. and then it will be shown inside stable area.
Rect stableBounds = new Rect();
diff --git a/services/core/java/com/android/server/wm/TaskPositioningController.java b/services/core/java/com/android/server/wm/TaskPositioningController.java
index e1123fa..c38e63e 100644
--- a/services/core/java/com/android/server/wm/TaskPositioningController.java
+++ b/services/core/java/com/android/server/wm/TaskPositioningController.java
@@ -169,7 +169,7 @@
mPositioningDisplay = displayContent;
mTaskPositioner = TaskPositioner.create(mService);
- mTaskPositioner.register(displayContent);
+ mTaskPositioner.register(displayContent, win);
// We need to grab the touch focus so that the touch events during the
// resizing/scrolling are not sent to the app. 'win' is the main window
@@ -187,7 +187,7 @@
return false;
}
- mTaskPositioner.startDrag(win, resize, preserveOrientation, startX, startY);
+ mTaskPositioner.startDrag(resize, preserveOrientation, startX, startY);
return true;
}
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 166bd05..56f4d32 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -52,11 +52,10 @@
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
import static android.view.Display.DEFAULT_DISPLAY;
-import static com.android.server.EventLogTags.WM_TASK_CREATED;
+import static com.android.server.EventLogTags.WM_TASK_REMOVED;
import static com.android.server.am.TaskRecordProto.ACTIVITIES;
import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE;
import static com.android.server.am.TaskRecordProto.BOUNDS;
-import static com.android.server.am.TaskRecordProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.TaskRecordProto.FULLSCREEN;
import static com.android.server.am.TaskRecordProto.ID;
import static com.android.server.am.TaskRecordProto.LAST_NON_FULLSCREEN_BOUNDS;
@@ -66,18 +65,15 @@
import static com.android.server.am.TaskRecordProto.REAL_ACTIVITY;
import static com.android.server.am.TaskRecordProto.RESIZE_MODE;
import static com.android.server.am.TaskRecordProto.STACK_ID;
+import static com.android.server.am.TaskRecordProto.TASK;
import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REMOVED;
import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
@@ -86,10 +82,6 @@
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
-import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static java.lang.Integer.MAX_VALUE;
@@ -144,7 +136,7 @@
import java.util.ArrayList;
import java.util.Objects;
-class TaskRecord extends ConfigurationContainer {
+class TaskRecord extends Task {
private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_ATM;
private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
@@ -213,7 +205,6 @@
*/
private static TaskRecordFactory sTaskRecordFactory;
- final int mTaskId; // Unique identifier for this task.
String affinity; // The affinity name for this task, or null; may change identity.
String rootAffinity; // Initial base affinity, or null; does not change from initial root.
final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
@@ -239,17 +230,11 @@
boolean hasBeenVisible; // Set if any activities in the task have been visible to the user.
String stringName; // caching of toString() result.
- int mUserId; // user for which this task was created
boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
// was changed.
int numFullscreen; // Number of fullscreen activities.
- int mResizeMode; // The resize mode of this task and its activities.
- // Based on the {@link ActivityInfo#resizeMode} of the root activity.
- private boolean mSupportsPictureInPicture; // Whether or not this task and its activities
- // support PiP. Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag
- // of the root activity.
/** Can't be put in lockTask mode. */
final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
/** Can enter app pinning with user approval. Can never start over existing lockTask task. */
@@ -265,13 +250,6 @@
int mLockTaskUid = -1; // The uid of the application that called startLockTask().
- // This represents the last resolved activity values for this task
- // NOTE: This value needs to be persisted with each task
- TaskDescription mTaskDescription;
-
- /** List of all activities in the task arranged in history order */
- final ArrayList<ActivityRecord> mActivities;
-
/** Current stack. Setter must always be used to update the value. */
private ActivityStack mStack;
@@ -309,8 +287,6 @@
int mCallingUid;
String mCallingPackage;
- final ActivityTaskManagerService mAtmService;
-
private final Rect mTmpStableBounds = new Rect();
private final Rect mTmpNonDecorBounds = new Rect();
private final Rect mTmpBounds = new Rect();
@@ -329,17 +305,9 @@
// This number will be assigned when we evaluate OOM scores for all visible tasks.
int mLayerRank = -1;
- // When non-empty, this represents the bounds this task will be drawn at. This gets set during
- // transient operations such as split-divider dragging and animations.
- // TODO(b/119687367): This member is temporary.
- final Rect mDisplayedBounds = new Rect();
-
/** Helper object used for updating override configuration. */
private Configuration mTmpConfig = new Configuration();
- // TODO: remove after unification
- Task mTask;
-
/** Used by fillTaskInfo */
final TaskActivitiesReport mReuseActivitiesReport = new TaskActivitiesReport();
@@ -347,21 +315,21 @@
* Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
* ActivityInfo, Intent, TaskDescription)} instead.
*/
- TaskRecord(ActivityTaskManagerService atmService, int _taskId, ActivityInfo info,
- Intent _intent, IVoiceInteractionSession _voiceSession,
- IVoiceInteractor _voiceInteractor, TaskDescription _taskDescription) {
+ TaskRecord(ActivityTaskManagerService atmService, int _taskId, ActivityInfo info, Intent _intent,
+ IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
+ TaskDescription _taskDescription, ActivityStack stack) {
this(atmService, _taskId, _intent, null /*_affinityIntent*/, null /*_affinity*/,
null /*_rootAffinity*/, null /*_realActivity*/, null /*_origActivity*/,
false /*_rootWasReset*/, false /*_autoRemoveRecents*/, false /*_askedCompatMode*/,
UserHandle.getUserId(info.applicationInfo.uid), 0 /*_effectiveUid*/,
- null /*_lastDescription*/, new ArrayList<>(), System.currentTimeMillis(),
+ null /*_lastDescription*/, System.currentTimeMillis(),
true /*neverRelinquishIdentity*/,
_taskDescription != null ? _taskDescription : new TaskDescription(),
_taskId, INVALID_TASK_ID, INVALID_TASK_ID, 0 /*taskAffiliationColor*/,
info.applicationInfo.uid, info.packageName, info.resizeMode,
info.supportsPictureInPicture(), false /*_realActivitySuspended*/,
false /*userSetupComplete*/, INVALID_MIN_SIZE, INVALID_MIN_SIZE, info,
- _voiceSession, _voiceInteractor);
+ _voiceSession, _voiceInteractor, stack);
}
/** Don't use constructor directly. This is only used by XML parser. */
@@ -369,15 +337,17 @@
Intent _affinityIntent, String _affinity, String _rootAffinity,
ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
- int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
+ int _effectiveUid, String _lastDescription,
long lastTimeMoved, boolean neverRelinquishIdentity,
TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended,
boolean userSetupComplete, int minWidth, int minHeight, ActivityInfo info,
- IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
- mAtmService = atmService;
- mTaskId = _taskId;
+ IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
+ ActivityStack stack) {
+ super(_taskId, stack != null ? stack.mTaskStack : null, _userId, resizeMode,
+ supportsPictureInPicture, _lastTaskDescription, atmService);
+ mRemoteToken = new RemoteToken(this);
affinityIntent = _affinityIntent;
affinity = _affinity;
rootAffinity = _rootAffinity;
@@ -390,15 +360,12 @@
isAvailable = true;
autoRemoveRecents = _autoRemoveRecents;
askedCompatMode = _askedCompatMode;
- mUserId = _userId;
mUserSetupComplete = userSetupComplete;
effectiveUid = _effectiveUid;
touchActiveTime();
lastDescription = _lastDescription;
- mActivities = activities;
mLastTimeMoved = lastTimeMoved;
mNeverRelinquishIdentity = neverRelinquishIdentity;
- mTaskDescription = _lastTaskDescription;
mAffiliatedTaskId = taskAffiliation;
mAffiliatedTaskColor = taskAffiliationColor;
mPrevAffiliateTaskId = prevTaskId;
@@ -406,7 +373,6 @@
mCallingUid = callingUid;
mCallingPackage = callingPackage;
mResizeMode = resizeMode;
- mSupportsPictureInPicture = supportsPictureInPicture;
if (info != null) {
setIntent(_intent, info);
setMinDimensions(info);
@@ -418,39 +384,6 @@
mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
}
- Task getTask() {
- return mTask;
- }
-
- void createTask(boolean onTop, boolean showForAllUsers) {
- if (mTask != null) {
- throw new IllegalArgumentException("mTask=" + mTask
- + " already created for task=" + this);
- }
-
- final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
- final TaskStack stack = getStack().getTaskStack();
-
- if (stack == null) {
- throw new IllegalArgumentException("TaskRecord: invalid stack=" + mStack);
- }
- EventLog.writeEvent(WM_TASK_CREATED, mTaskId, stack.mStackId);
- mTask = new Task(mTaskId, stack, mUserId, mAtmService.mWindowManager, mResizeMode,
- mSupportsPictureInPicture, mTaskDescription, this);
- final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
-
- if (!mDisplayedBounds.isEmpty()) {
- mTask.setOverrideDisplayedBounds(mDisplayedBounds);
- }
- // We only want to move the parents to the parents if we are creating this task at the
- // top of its stack.
- stack.addTask(mTask, position, showForAllUsers, onTop /* moveParents */);
- }
-
- void setTask(Task task) {
- mTask = task;
- }
-
void cleanUpResourcesForDestroy() {
if (hasChild()) {
return;
@@ -473,60 +406,33 @@
mAtmService.mStackSupervisor.mRecentTasks.remove(this);
}
- removeWindowContainer();
+ removeIfPossible();
}
@VisibleForTesting
- void removeWindowContainer() {
+ @Override
+ void removeIfPossible() {
mAtmService.getLockTaskController().clearLockedTask(this);
- if (mTask == null) {
- if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + mTaskId);
- return;
- }
- mTask.removeIfPossible();
- mTask = null;
- if (!getWindowConfiguration().persistTaskBounds()) {
- // Reset current bounds for task whose bounds shouldn't be persisted so it uses
- // default configuration the next time it launches.
- setBounds(null);
- }
+ super.removeIfPossible();
mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId);
}
- void onSnapshotChanged(TaskSnapshot snapshot) {
- mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(mTaskId, snapshot);
- }
-
void setResizeMode(int resizeMode) {
if (mResizeMode == resizeMode) {
return;
}
mResizeMode = resizeMode;
- mTask.setResizeable(resizeMode);
mAtmService.mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities();
}
- void setTaskDockedResizing(boolean resizing) {
- if (mTask == null) {
- Slog.w(TAG_WM, "setTaskDockedResizing: taskId " + mTaskId + " not found.");
- return;
- }
- mTask.setTaskDockedResizing(resizing);
- }
-
- // TODO: Consolidate this with the resize() method below.
- public void requestResize(Rect bounds, int resizeMode) {
- mAtmService.resizeTask(mTaskId, bounds, resizeMode);
- }
-
boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
mAtmService.deferWindowLayout();
try {
final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
- if (mTask == null) {
+ if (getParent() == null) {
// Task doesn't exist in window manager yet (e.g. was restored from recents).
// All we can do for now is update the bounds so it can be used when the task is
// added to window manager.
@@ -577,7 +483,7 @@
}
}
}
- mTask.resize(kept, forced);
+ resize(kept, forced);
saveLaunchingStateIfNeeded();
@@ -588,19 +494,6 @@
}
}
- // TODO: Investigate combining with the resize() method above.
- void resizeWindowContainer() {
- mTask.resize(false /* relayout */, false /* forced */);
- }
-
- void getWindowContainerBounds(Rect bounds) {
- if (mTask != null) {
- mTask.getBounds(bounds);
- } else {
- bounds.setEmpty();
- }
- }
-
/**
* Convenience method to reparent a task to the top or bottom position of the stack.
*/
@@ -708,32 +601,16 @@
// Adjust the position for the new parent stack as needed.
position = toStack.getAdjustedPositionForTask(this, position, null /* starting */);
- // Must reparent first in window manager to avoid a situation where AM can delete the
- // we are coming from in WM before we reparent because it became empty.
- mTask.reparent(toStack.getTaskStack(), position,
- moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
-
final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
|| (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
- // Move the task
- sourceStack.removeTask(this, reason, moveStackToFront
- ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
- toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
+
+ reparent(toStack.getTaskStack(), position, moveStackToFront, reason);
if (schedulePictureInPictureModeChange) {
// Notify of picture-in-picture mode changes
supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
}
- // TODO: Ensure that this is actually necessary here
- // Notify the voice session if required
- if (voiceSession != null) {
- try {
- voiceSession.taskStarted(intent, mTaskId);
- } catch (RemoteException e) {
- }
- }
-
// If the task had focus before (or we're requested to move focus), move focus to the
// new stack by moving the stack to the front.
if (r != null) {
@@ -809,14 +686,6 @@
|| targetWindowingMode == WINDOWING_MODE_FREEFORM;
}
- void cancelWindowTransition() {
- if (mTask == null) {
- Slog.w(TAG_WM, "cancelWindowTransition: taskId " + mTaskId + " not found.");
- return;
- }
- mTask.cancelTaskWindowTransition();
- }
-
/**
* DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
*/
@@ -966,71 +835,109 @@
mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.mTaskId;
}
- <T extends ActivityStack> T getStack() {
- return (T) mStack;
+ ActivityStack getStack() {
+ return mStack;
}
- /**
- * Must be used for setting parent stack because it performs configuration updates.
- * Must be called after adding task as a child to the stack.
- */
- // TODO(task-unify): Remove or rework after task level unification.
- void setStack(ActivityStack stack) {
- if (stack != null && !stack.isInStackLocked(this)) {
- throw new IllegalStateException("Task must be added as a Stack child first.");
- }
- final ActivityStack oldStack = mStack;
- mStack = stack;
+ // TODO(stack-unify): Can be removed on stack unified.
+ void onParentChanged(ActivityStack newParent, ActivityStack oldParent) {
+ onParentChanged(
+ newParent != null ? newParent.mTaskStack : null,
+ oldParent != null ? oldParent.mTaskStack : null);
+ }
- // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this
- // {@link ActivityRecord} from its current {@link ActivityStack}.
+ @Override
+ void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
+ final ActivityStack oldStack = (oldParent != null)
+ ? ((TaskStack) oldParent).mActivityStack : null;
+ final ActivityStack newStack = (newParent != null)
+ ? ((TaskStack) newParent).mActivityStack : null;
- if (oldStack != mStack) {
+ mStack = newStack;
+
+ super.onParentChanged(newParent, oldParent);
+
+ if (oldStack != null) {
for (int i = getChildCount() - 1; i >= 0; --i) {
final ActivityRecord activity = getChildAt(i);
+ oldStack.onActivityRemovedFromStack(activity);
+ }
- if (oldStack != null) {
- oldStack.onActivityRemovedFromStack(activity);
- }
+ updateTaskMovement(true /*toFront*/);
- if (mStack != null) {
- stack.onActivityAddedToStack(activity);
+ if (oldStack.inPinnedWindowingMode()
+ && (newStack == null || !newStack.inPinnedWindowingMode())) {
+ // Notify if a task from the pinned stack is being removed
+ // (or moved depending on the mode).
+ mAtmService.getTaskChangeNotificationController().notifyActivityUnpinned();
+ }
+ }
+
+ if (newStack != null) {
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final ActivityRecord activity = getChildAt(i);
+ newStack.onActivityAddedToStack(activity);
+ }
+
+ // TODO: Ensure that this is actually necessary here
+ // Notify the voice session if required
+ if (voiceSession != null) {
+ try {
+ voiceSession.taskStarted(intent, mTaskId);
+ } catch (RemoteException e) {
}
}
}
- onParentChanged(mStack, oldStack);
+ // First time we are adding the task to the system.
+ if (oldParent == null && newParent != null) {
+
+ // TODO: Super random place to be doing this, but aligns with what used to be done
+ // before we unified Task level. Look into if this can be done in a better place.
+ updateOverrideConfigurationFromLaunchBounds();
+ }
+
+ // Task is being removed.
+ if (oldParent != null && newParent == null) {
+ cleanUpResourcesForDestroy();
+ }
+
+
+ // Update task bounds if needed.
+ adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
+
+ if (getWindowConfiguration().windowsAreScaleable()) {
+ // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
+ // while a resize is pending.
+ forceWindowsScaleable(true /* force */);
+ } else {
+ forceWindowsScaleable(false /* force */);
+ }
+
+ mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
+ }
+
+ /** TODO(task-merge): Consolidate into {@link TaskStack#onChildPositionChanged}. */
+ void updateTaskMovement(boolean toFront) {
+ if (isPersistable) {
+ mLastTimeMoved = System.currentTimeMillis();
+ // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
+ // recently will be most negative, tasks sent to the bottom before that will be less
+ // negative. Similarly for recent tasks moved to the top which will be most positive.
+ if (!toFront) {
+ mLastTimeMoved *= -1;
+ }
+ }
+ mAtmService.mRootActivityContainer.invalidateTaskLayers();
}
/**
- * @return Id of current stack, {@link INVALID_STACK_ID} if no stack is set.
+ * @return Id of current stack, {@link ActivityTaskManager#INVALID_STACK_ID} if no stack is set.
*/
int getStackId() {
return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
}
- @Override
- protected int getChildCount() {
- return mActivities.size();
- }
-
- @Override
- protected ActivityRecord getChildAt(int index) {
- return mActivities.get(index);
- }
-
- @Override
- protected ConfigurationContainer getParent() {
- return mStack;
- }
-
- @Override
- protected void onParentChanged(
- ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- super.onParentChanged(newParent, oldParent);
- mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
- }
-
// Close up recents linked list.
private void closeRecentsChain() {
if (mPrevAffiliate != null) {
@@ -1121,16 +1028,6 @@
return null;
}
- boolean isVisible() {
- for (int i = getChildCount() - 1; i >= 0; --i) {
- final ActivityRecord r = getChildAt(i);
- if (r.visible) {
- return true;
- }
- }
- return false;
- }
-
/**
* Return true if any activities in this task belongs to input uid.
*/
@@ -1210,15 +1107,10 @@
* Reorder the history stack so that the passed activity is brought to the front.
*/
final void moveActivityToFrontLocked(ActivityRecord newTop) {
- if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
- "Removing and adding activity " + newTop
- + " to stack at top callers=" + Debug.getCallers(4));
+ if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, "Removing and adding activity "
+ + newTop + " to stack at top callers=" + Debug.getCallers(4));
- mActivities.remove(newTop);
- mActivities.add(newTop);
-
- // Make sure window manager is aware of the position change.
- mTask.positionChildAtTop(newTop);
+ positionChildAtTop(newTop);
updateEffectiveIntent();
}
@@ -1232,19 +1124,29 @@
return getChildAt(0).getActivityType();
}
- /** Called when a Task child is added from the Task.java side. */
- // TODO(task-unify): Just override addChild to do what is needed when someone calls to add a
- // child.
- void onChildAdded(ActivityRecord r, int index) {
+ @Override
+ void addChild(ActivityRecord r, int index) {
+ if (r.getParent() != null) {
+ // Shouldn't already have a parent since we are just adding to the task...Maybe you
+ // meant to use reparent?
+ throw new IllegalStateException(
+ "r=" + r + " parent=" + r.getParent() + " task=" + this);
+ }
+
+ // If this task had any child before we added this one.
+ boolean hadChild = hasChild();
+
+ index = getAdjustedAddPosition(r, index);
+ super.addChild(r, index);
+
+ ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
r.inHistory = true;
- // Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
- if (!mActivities.remove(r) && r.occludesParent()) {
- // Was not previously in list.
+ if (r.occludesParent()) {
numFullscreen++;
}
// Only set this based on the first activity
- if (!hasChild()) {
+ if (!hadChild) {
if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
// Normally non-standard activity type for the activity record will be set when the
// object is created, however we delay setting the standard application type until
@@ -1264,20 +1166,6 @@
r.setActivityType(getActivityType());
}
- final int size = getChildCount();
-
- if (index == size && size > 0) {
- final ActivityRecord top = getChildAt(size - 1);
- if (top.mTaskOverlay) {
- // Place below the task overlay activity since the overlay activity should always
- // be on top.
- index--;
- }
- }
-
- index = Math.min(size, index);
- mActivities.add(index, r);
-
updateEffectiveIntent();
if (r.isPersistable()) {
mAtmService.notifyTaskPersisterLocked(this, false);
@@ -1288,31 +1176,23 @@
mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
}
- // TODO(task-unify): Merge onChildAdded method below into this since task will be a single
- // object.
void addChild(ActivityRecord r) {
- if (r.getParent() != null) {
- // Shouldn't already have a parent since we are just adding to the task...
- throw new IllegalStateException(
- "r=" + r + " parent=" + r.getParent() + " task=" + this);
- }
-
- ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
- // This means the activity isn't attached to Task.java yet. Go ahead and do that.
- // TODO(task-unify): Remove/call super once we unify task level.
- if (mTask != null) {
- mTask.addChild(r, Integer.MAX_VALUE /* add on top */);
- } else {
- onChildAdded(r, Integer.MAX_VALUE);
- }
+ addChild(r, Integer.MAX_VALUE /* add on top */);
}
- /** Called when a Task child is removed from the Task.java side. */
- // TODO(task-unify): Just override removeChild to do what is needed when someone calls to remove
- // a child.
- void onChildRemoved(ActivityRecord r) {
- if (mActivities.remove(r) && r.occludesParent()) {
- // Was previously in list.
+ @Override
+ void removeChild(ActivityRecord r) {
+ removeChild(r, "removeChild");
+ }
+
+ void removeChild(ActivityRecord r, String reason) {
+ if (!mChildren.contains(r)) {
+ Slog.e(TAG, "removeChild: r=" + r + " not found in t=" + this);
+ return;
+ }
+
+ super.removeChild(r);
+ if (r.occludesParent()) {
numFullscreen--;
}
if (r.isPersistable()) {
@@ -1336,16 +1216,19 @@
// When destroying a task, tell the supervisor to remove it so that any activity it
// has can be cleaned up correctly. This is currently the only place where we remove
// a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
- // state into removeTask(), we just clear the task here before the other residual
+ // state into removeChild(), we just clear the task here before the other residual
// work.
- // TODO: If the callers to removeTask() changes such that we have multiple places
- // where we are destroying the task, move this back into removeTask()
+ // TODO: If the callers to removeChild() changes such that we have multiple places
+ // where we are destroying the task, move this back into removeChild()
mAtmService.mStackSupervisor.removeTaskByIdLocked(mTaskId, false /* killProcess */,
- !REMOVE_FROM_RECENTS, "onChildRemoved");
+ !REMOVE_FROM_RECENTS, reason);
}
} else if (!mReuseTask) {
// Remove entire task if it doesn't have any activity left and it isn't marked for reuse
- mStack.removeTask(this, "onChildRemoved", REMOVE_TASK_MODE_DESTROYING);
+ mStack.removeChild(this, reason);
+ EventLog.writeEvent(WM_TASK_REMOVED, mTaskId,
+ "removeChild: last r=" + r + " in t=" + this);
+ removeIfPossible();
}
}
@@ -1380,7 +1263,7 @@
* Completely remove all activities associated with an existing
* task starting at a specified index.
*/
- final void performClearTaskAtIndexLocked(int activityNdx, String reason) {
+ private void performClearTaskAtIndexLocked(int activityNdx, String reason) {
int numActivities = getChildCount();
for ( ; activityNdx < numActivities; ++activityNdx) {
final ActivityRecord r = getChildAt(activityNdx);
@@ -1390,7 +1273,7 @@
if (mStack == null) {
// Task was restored from persistent storage.
r.takeFromHistory();
- mActivities.remove(activityNdx);
+ removeChild(r);
--activityNdx;
--numActivities;
} else if (r.finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason,
@@ -1526,20 +1409,13 @@
" mLockTaskAuth=" + lockTaskAuthToString());
}
- private boolean isResizeable(boolean checkSupportsPip) {
- return (mAtmService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
- || (checkSupportsPip && mSupportsPictureInPicture));
- }
-
- boolean isResizeable() {
- return isResizeable(true /* checkSupportsPip */);
- }
-
@Override
public boolean supportsSplitScreenWindowingMode() {
// A task can not be docked even if it is considered resizeable because it only supports
// picture-in-picture mode but has a non-resizeable resizeMode
return super.supportsSplitScreenWindowingMode()
+ // TODO(task-group): Probably makes sense to move this and associated code into
+ // WindowContainer so it affects every node.
&& mAtmService.mSupportsSplitScreenMultiWindow
&& (mAtmService.mForceResizableActivities
|| (isResizeable(false /* checkSupportsPip */)
@@ -1672,15 +1548,13 @@
}
topActivity = false;
}
- mTaskDescription = new TaskDescription(label, null, iconResource, iconFilename,
- colorPrimary, colorBackground, statusBarColor, navigationBarColor,
+ final TaskDescription taskDescription = new TaskDescription(label, null, iconResource,
+ iconFilename, colorPrimary, colorBackground, statusBarColor, navigationBarColor,
statusBarContrastWhenTransparent, navigationBarContrastWhenTransparent);
- if (mTask != null) {
- mTask.setTaskDescription(mTaskDescription);
- }
+ setTaskDescription(taskDescription);
// Update the task affiliation color if we are the parent of the group
if (mTaskId == mAffiliatedTaskId) {
- mAffiliatedTaskColor = mTaskDescription.getPrimaryColor();
+ mAffiliatedTaskColor = taskDescription.getPrimaryColor();
}
}
}
@@ -1903,38 +1777,6 @@
}
/**
- * Displayed bounds are used to set where the task is drawn at any given time. This is
- * separate from its actual bounds so that the app doesn't see any meaningful configuration
- * changes during transitionary periods.
- */
- void setDisplayedBounds(Rect bounds) {
- if (bounds == null) {
- mDisplayedBounds.setEmpty();
- } else {
- mDisplayedBounds.set(bounds);
- }
- if (mTask != null) {
- mTask.setOverrideDisplayedBounds(
- mDisplayedBounds.isEmpty() ? null : mDisplayedBounds);
- }
- }
-
- /**
- * Gets the current overridden displayed bounds. These will be empty if the task is not
- * currently overriding where it is displayed.
- */
- Rect getDisplayedBounds() {
- return mDisplayedBounds;
- }
-
- /**
- * @return {@code true} if this has overridden displayed bounds.
- */
- boolean hasDisplayedBounds() {
- return !mDisplayedBounds.isEmpty();
- }
-
- /**
* Intersects inOutBounds with intersectBounds-intersectInsets. If inOutBounds is larger than
* intersectBounds on a side, then the respective side will not be intersected.
*
@@ -2190,16 +2032,10 @@
computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
}
- /** @see WindowContainer#handlesOrientationChangeFromDescendant */
- boolean handlesOrientationChangeFromDescendant() {
- return mTask != null && mTask.getParent() != null
- && mTask.getParent().handlesOrientationChangeFromDescendant();
- }
-
/**
- * Compute bounds (letterbox or pillarbox) for {@link #WINDOWING_MODE_FULLSCREEN} when the
- * parent doesn't handle the orientation change and the requested orientation is different from
- * the parent.
+ * Compute bounds (letterbox or pillarbox) for
+ * {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN} when the parent doesn't handle the
+ * orientation change and the requested orientation is different from the parent.
*/
void computeFullscreenBounds(@NonNull Rect outBounds, @Nullable ActivityRecord refActivity,
@NonNull Rect parentBounds, int parentOrientation) {
@@ -2345,7 +2181,7 @@
info.realActivity = realActivity;
info.numActivities = mReuseActivitiesReport.numActivities;
info.lastActiveTime = lastActiveTime;
- info.taskDescription = new ActivityManager.TaskDescription(mTaskDescription);
+ info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription());
info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
info.resizeMode = mResizeMode;
info.configuration.setTo(getConfiguration());
@@ -2435,7 +2271,7 @@
}
pw.println(")");
}
- pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
+ pw.print(prefix); pw.print("Activities="); pw.println(mChildren);
if (!askedCompatMode || !inRecents || !isAvailable) {
pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
pw.print(" inRecents="); pw.print(inRecents);
@@ -2490,6 +2326,7 @@
return toString();
}
+ @Override
public void writeToProto(ProtoOutputStream proto, long fieldId,
@WindowTraceLogLevel int logLevel) {
if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
@@ -2497,13 +2334,13 @@
}
final long token = proto.start(fieldId);
- super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
+ writeToProtoInnerTaskOnly(proto, TASK, logLevel);
proto.write(ID, mTaskId);
for (int i = getChildCount() - 1; i >= 0; i--) {
- ActivityRecord activity = getChildAt(i);
+ final ActivityRecord activity = getChildAt(i);
activity.writeToProto(proto, ACTIVITIES);
}
- proto.write(STACK_ID, mStack.mStackId);
+ proto.write(STACK_ID, getStackId());
if (mLastNonFullscreenBounds != null) {
mLastNonFullscreenBounds.writeToProto(proto, LAST_NON_FULLSCREEN_BOUNDS);
}
@@ -2579,8 +2416,8 @@
if (lastDescription != null) {
out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
}
- if (mTaskDescription != null) {
- mTaskDescription.saveToXml(out);
+ if (getTaskDescription() != null) {
+ getTaskDescription().saveToXml(out);
}
out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
@@ -2641,14 +2478,14 @@
static TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Intent intent, IVoiceInteractionSession voiceSession,
- IVoiceInteractor voiceInteractor) {
+ IVoiceInteractor voiceInteractor, ActivityStack stack) {
return getTaskRecordFactory().create(
- service, taskId, info, intent, voiceSession, voiceInteractor);
+ service, taskId, info, intent, voiceSession, voiceInteractor, stack);
}
static TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent, TaskDescription taskDescription) {
- return getTaskRecordFactory().create(service, taskId, info, intent, taskDescription);
+ Intent intent, TaskDescription taskDescription, ActivityStack stack) {
+ return getTaskRecordFactory().create(service, taskId, info, intent, taskDescription, stack);
}
static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
@@ -2665,15 +2502,15 @@
TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Intent intent, IVoiceInteractionSession voiceSession,
- IVoiceInteractor voiceInteractor) {
+ IVoiceInteractor voiceInteractor, ActivityStack stack) {
return new TaskRecord(service, taskId, info, intent, voiceSession, voiceInteractor,
- null /*taskDescription*/);
+ null /*taskDescription*/, stack);
}
TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent, TaskDescription taskDescription) {
+ Intent intent, TaskDescription taskDescription, ActivityStack stack) {
return new TaskRecord(service, taskId, info, intent, null /*voiceSession*/,
- null /*voiceInteractor*/, taskDescription);
+ null /*voiceInteractor*/, taskDescription, stack);
}
/**
@@ -2683,20 +2520,20 @@
Intent affinityIntent, String affinity, String rootAffinity,
ComponentName realActivity, ComponentName origActivity, boolean rootWasReset,
boolean autoRemoveRecents, boolean askedCompatMode, int userId,
- int effectiveUid, String lastDescription, ArrayList<ActivityRecord> activities,
+ int effectiveUid, String lastDescription,
long lastTimeMoved, boolean neverRelinquishIdentity,
TaskDescription lastTaskDescription, int taskAffiliation, int prevTaskId,
int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
int resizeMode, boolean supportsPictureInPicture, boolean realActivitySuspended,
- boolean userSetupComplete, int minWidth, int minHeight) {
+ boolean userSetupComplete, int minWidth, int minHeight, ActivityStack stack) {
return new TaskRecord(service, taskId, intent, affinityIntent, affinity,
rootAffinity, realActivity, origActivity, rootWasReset, autoRemoveRecents,
- askedCompatMode, userId, effectiveUid, lastDescription, activities,
+ askedCompatMode, userId, effectiveUid, lastDescription,
lastTimeMoved, neverRelinquishIdentity, lastTaskDescription, taskAffiliation,
prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
resizeMode, supportsPictureInPicture, realActivitySuspended, userSetupComplete,
minWidth, minHeight, null /*ActivityInfo*/, null /*_voiceSession*/,
- null /*_voiceInteractor*/);
+ null /*_voiceInteractor*/, stack);
}
TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
@@ -2908,15 +2745,15 @@
taskId, intent, affinityIntent,
affinity, rootAffinity, realActivity, origActivity, rootHasReset,
autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
- activities, lastTimeOnTop, neverRelinquishIdentity, taskDescription,
+ lastTimeOnTop, neverRelinquishIdentity, taskDescription,
taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
callingPackage, resizeMode, supportsPictureInPicture, realActivitySuspended,
- userSetupComplete, minWidth, minHeight);
+ userSetupComplete, minWidth, minHeight, null /*stack*/);
task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
task.setBounds(lastNonFullscreenBounds);
for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
- activities.get(activityNdx).setTask(task);
+ task.addChild(activities.get(activityNdx));
}
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 3552245..e82525a 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -52,6 +52,8 @@
import static com.android.server.wm.StackProto.MINIMIZE_AMOUNT;
import static com.android.server.wm.StackProto.TASKS;
import static com.android.server.wm.StackProto.WINDOW_CONTAINER;
+import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -69,6 +71,7 @@
import android.util.proto.ProtoOutputStream;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
+import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import com.android.internal.annotations.VisibleForTesting;
@@ -81,7 +84,7 @@
import java.util.ArrayList;
import java.util.List;
-public class TaskStack extends WindowContainer<Task> implements
+public class TaskStack extends WindowContainer<TaskRecord> implements
BoundsAnimationTarget, ConfigurationContainerListener {
/** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
* restrict IME adjustment so that a min portion of top stack remains visible.*/
@@ -99,7 +102,6 @@
private Rect mTmpRect3 = new Rect();
/** For Pinned stack controlling. */
- private Rect mTmpFromBounds = new Rect();
private Rect mTmpToBounds = new Rect();
/** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
@@ -113,7 +115,6 @@
/** ActivityRecords that are exiting, but still on screen for animations. */
final ArrayList<ActivityRecord> mExitingActivities = new ArrayList<>();
- final ArrayList<ActivityRecord> mTmpActivities = new ArrayList<>();
/** Detach this stack from its display when animation completes. */
// TODO: maybe tie this to WindowContainer#removeChild some how...
@@ -327,7 +328,7 @@
}
/** Bounds of the stack with other system factors taken into consideration. */
- public void getDimBounds(Rect out) {
+ void getDimBounds(Rect out) {
getBounds(out);
}
@@ -479,11 +480,6 @@
dividerSize);
}
- // TODO: Checkout the call points of this method and the ones below to see how they can fit in WC.
- void addTask(Task task, int position) {
- addTask(task, position, task.showForAllUsers(), true /* moveParents */);
- }
-
/**
* Put a Task in this stack. Used for adding only.
* When task is added to top of the stack, the entire branch of the hierarchy (including stack
@@ -492,22 +488,19 @@
* @param position Target position to add the task to.
* @param showForAllUsers Whether to show the task regardless of the current user.
*/
- void addTask(Task task, int position, boolean showForAllUsers, boolean moveParents) {
- final TaskStack currentStack = task.mStack;
- // TODO: We pass stack to task's constructor, but we still need to call this method.
- // This doesn't make sense, mStack will already be set equal to "this" at this point.
- if (currentStack != null && currentStack.mStackId != mStackId) {
- throw new IllegalStateException("Trying to add taskId=" + task.mTaskId
- + " to stackId=" + mStackId
- + ", but it is already attached to stackId=" + task.mStack.mStackId);
- }
-
+ void addChild(TaskRecord task, int position, boolean showForAllUsers, boolean moveParents) {
// Add child task.
- task.mStack = this;
addChild(task, null);
// Move child to a proper position, as some restriction for position might apply.
- positionChildAt(position, task, moveParents /* includingParents */, showForAllUsers);
+ position = positionChildAt(
+ position, task, moveParents /* includingParents */, showForAllUsers);
+ mActivityStack.onChildAdded(task, position);
+ }
+
+ @Override
+ void addChild(TaskRecord task, int position) {
+ addChild(task, position, task.showForAllUsers(), false /* includingParents */);
}
void positionChildAt(Task child, int position) {
@@ -524,7 +517,7 @@
getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
}
- void positionChildAtTop(Task child, boolean includingParents) {
+ void positionChildAtTop(TaskRecord child, boolean includingParents) {
if (child == null) {
// TODO: Fix the call-points that cause this to happen.
return;
@@ -539,7 +532,7 @@
displayContent.layoutAndAssignWindowLayersIfNeeded();
}
- void positionChildAtBottom(Task child, boolean includingParents) {
+ void positionChildAtBottom(TaskRecord child, boolean includingParents) {
if (child == null) {
// TODO: Fix the call-points that cause this to happen.
return;
@@ -554,19 +547,18 @@
}
@Override
- void positionChildAt(int position, Task child, boolean includingParents) {
+ void positionChildAt(int position, TaskRecord child, boolean includingParents) {
positionChildAt(position, child, includingParents, child.showForAllUsers());
}
/**
* Overridden version of {@link TaskStack#positionChildAt(int, Task, boolean)}. Used in
- * {@link TaskStack#addTask(Task, int, boolean showForAllUsers, boolean)}, as it can receive
- * showForAllUsers param from {@link AppWindowToken} instead of {@link Task#showForAllUsers()}.
+ * {@link TaskStack#addChild(Task, int, boolean showForAllUsers, boolean)}, as it can receive
+ * showForAllUsers param from {@link ActivityRecord} instead of {@link Task#showForAllUsers()}.
*/
- private void positionChildAt(int position, Task child, boolean includingParents,
+ int positionChildAt(int position, TaskRecord child, boolean includingParents,
boolean showForAllUsers) {
- final int targetPosition = findPositionForTask(child, position, showForAllUsers,
- false /* addingNew */);
+ final int targetPosition = findPositionForTask(child, position, showForAllUsers);
super.positionChildAt(targetPosition, child, includingParents);
// Log positioning.
@@ -575,6 +567,14 @@
final int toTop = targetPosition == mChildren.size() - 1 ? 1 : 0;
EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, child.mTaskId, toTop, targetPosition);
+
+ return targetPosition;
+ }
+
+ @Override
+ void onChildPositionChanged(WindowContainer child) {
+ // TODO(task-merge): Read comment on updateTaskMovement method.
+ //((TaskRecord) child).updateTaskMovement(true);
}
void reparent(int displayId, Rect outStackBounds, boolean onTop) {
@@ -594,14 +594,13 @@
// TODO: We should really have users as a window container in the hierarchy so that we don't
// have to do complicated things like we are doing in this method.
- private int findPositionForTask(Task task, int targetPosition, boolean showForAllUsers,
- boolean addingNew) {
+ private int findPositionForTask(Task task, int targetPosition, boolean showForAllUsers) {
final boolean canShowTask =
showForAllUsers || mWmService.isCurrentProfileLocked(task.mUserId);
final int stackSize = mChildren.size();
int minPosition = 0;
- int maxPosition = addingNew ? stackSize : stackSize - 1;
+ int maxPosition = stackSize - 1;
if (canShowTask) {
minPosition = computeMinPosition(minPosition, stackSize);
@@ -612,8 +611,7 @@
// preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.
if (targetPosition == POSITION_BOTTOM && minPosition == 0) {
return POSITION_BOTTOM;
- } else if (targetPosition == POSITION_TOP
- && maxPosition == (addingNew ? stackSize : stackSize - 1)) {
+ } else if (targetPosition == POSITION_TOP && maxPosition == (stackSize - 1)) {
return POSITION_TOP;
}
// Reset position based on minimum/maximum possible positions.
@@ -665,25 +663,16 @@
* @param task The Task to delete.
*/
@Override
- void removeChild(Task task) {
+ void removeChild(TaskRecord task) {
+ if (!mChildren.contains(task)) {
+ // Not really in this stack anymore...
+ return;
+ }
if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "removeChild: task=" + task);
super.removeChild(task);
- task.mStack = null;
- if (mDisplayContent != null) {
- if (mChildren.isEmpty()) {
- getParent().positionChildAt(POSITION_BOTTOM, this, false /* includingParents */);
- }
- mDisplayContent.setLayoutNeeded();
- }
- for (int appNdx = mExitingActivities.size() - 1; appNdx >= 0; --appNdx) {
- final ActivityRecord activity = mExitingActivities.get(appNdx);
- if (activity.getTask() == task) {
- activity.mIsExiting = false;
- mExitingActivities.remove(appNdx);
- }
- }
+ mActivityStack.onChildRemoved(task, mDisplayContent);
}
@Override
@@ -934,7 +923,7 @@
@Override
void removeIfPossible() {
- if (isSelfOrChildAnimating()) {
+ if (isAnimating(TRANSITION | CHILDREN)) {
mDeferRemoval = true;
return;
}
@@ -969,7 +958,7 @@
super.switchUser();
int top = mChildren.size();
for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
- Task task = mChildren.get(taskNdx);
+ TaskRecord task = mChildren.get(taskNdx);
if (mWmService.isCurrentProfileLocked(task.mUserId) || task.showForAllUsers()) {
mChildren.remove(taskNdx);
mChildren.add(task);
@@ -1295,7 +1284,7 @@
super.writeToProto(proto, WINDOW_CONTAINER, logLevel);
proto.write(ID, mStackId);
for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
- mChildren.get(taskNdx).writeToProto(proto, TASKS, logLevel);
+ mChildren.get(taskNdx).writeToProtoInnerTaskOnly(proto, TASKS, logLevel);
}
proto.write(FILLS_PARENT, matchParentBounds());
getRawBounds().writeToProto(proto, BOUNDS);
@@ -1792,7 +1781,7 @@
/** Returns true if a removal action is still being deferred. */
boolean checkCompleteDeferredRemoval() {
- if (isSelfOrChildAnimating()) {
+ if (isAnimating(TRANSITION | CHILDREN)) {
return true;
}
if (mDeferRemoval) {
@@ -1866,4 +1855,22 @@
AnimatingActivityRegistry getAnimatingActivityRegistry() {
return mAnimatingActivityRegistry;
}
+
+ @Override
+ void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
+ Rect outSurfaceInsets) {
+ final Task task = getTopChild();
+ if (task != null) {
+ task.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
+ } else {
+ super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
+ }
+ }
+
+ @Override
+ RemoteAnimationTarget createRemoteAnimationTarget(
+ RemoteAnimationController.RemoteAnimationRecord record) {
+ final Task task = getTopChild();
+ return task != null ? task.createRemoteAnimationTarget(record) : null;
+ }
}
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 1e13aef..3632284 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -24,6 +24,8 @@
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
@@ -118,7 +120,8 @@
}
mFindResults.resetTopWallpaper = true;
- if (w.mActivityRecord != null && w.mActivityRecord.isHidden() && !w.mActivityRecord.isSelfAnimating()) {
+ if (w.mActivityRecord != null && w.mActivityRecord.isHidden()
+ && !w.mActivityRecord.isAnimating(TRANSITION)) {
// If this window's app token is hidden and not animating, it is of no interest to us.
if (DEBUG_WALLPAPER) Slog.v(TAG, "Skipping hidden and not animating token: " + w);
@@ -136,7 +139,7 @@
}
final boolean keyguardGoingAwayWithWallpaper = (w.mActivityRecord != null
- && w.mActivityRecord.isSelfAnimating()
+ && w.mActivityRecord.isAnimating(TRANSITION)
&& AppTransition.isKeyguardGoingAwayTransit(w.mActivityRecord.getTransit())
&& (w.mActivityRecord.getTransitFlags()
& TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0);
@@ -159,7 +162,8 @@
final RecentsAnimationController recentsAnimationController =
mService.getRecentsAnimationController();
- final boolean animationWallpaper = w.mActivityRecord != null && w.mActivityRecord.getAnimation() != null
+ final boolean animationWallpaper = w.mActivityRecord != null
+ && w.mActivityRecord.getAnimation() != null
&& w.mActivityRecord.getAnimation().getShowWallpaper();
final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0
|| animationWallpaper;
@@ -173,7 +177,7 @@
&& (mWallpaperTarget == w || w.isDrawFinishedLw())) {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Found wallpaper target: " + w);
mFindResults.setWallpaperTarget(w);
- if (w == mWallpaperTarget && w.isAnimating()) {
+ if (w == mWallpaperTarget && w.isAnimating(TRANSITION | PARENTS)) {
// The current wallpaper target is animating, so we'll look behind it for
// another possible target and figure out what is going on later.
if (DEBUG_WALLPAPER) Slog.v(TAG,
@@ -224,19 +228,19 @@
if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
+ (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
+ " animating=" + ((wallpaperTarget != null && wallpaperTarget.mActivityRecord != null)
- ? wallpaperTarget.mActivityRecord.isSelfAnimating() : null)
+ ? wallpaperTarget.mActivityRecord.isAnimating(TRANSITION) : null)
+ " prev=" + mPrevWallpaperTarget
+ " recentsAnimationWallpaperVisible=" + isAnimatingWithRecentsComponent);
return (wallpaperTarget != null
&& (!wallpaperTarget.mObscured
|| isAnimatingWithRecentsComponent
|| (wallpaperTarget.mActivityRecord != null
- && wallpaperTarget.mActivityRecord.isSelfAnimating())))
+ && wallpaperTarget.mActivityRecord.isAnimating(TRANSITION))))
|| mPrevWallpaperTarget != null;
}
boolean isWallpaperTargetAnimating() {
- return mWallpaperTarget != null && mWallpaperTarget.isAnimating()
+ return mWallpaperTarget != null && mWallpaperTarget.isAnimating(TRANSITION | PARENTS)
&& (mWallpaperTarget.mActivityRecord == null
|| !mWallpaperTarget.mActivityRecord.isWaitingForTransitionStart());
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 3a1d6e0..f7525a9 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -17,6 +17,8 @@
package com.android.server.wm;
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -192,7 +194,7 @@
mService.mWindowPlacerLocked.requestTraversal();
}
- final boolean rootAnimating = mService.mRoot.isSelfOrChildAnimating();
+ final boolean rootAnimating = mService.mRoot.isAnimating(TRANSITION | CHILDREN);
if (rootAnimating && !mLastRootAnimating) {
// Usually app transitions but quite a load onto the system already (with all the
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index a620a7c..11658f9 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -24,8 +24,15 @@
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.SurfaceControl.Transaction;
+import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
+import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
+import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainerProto.CONFIGURATION_CONTAINER;
import static com.android.server.wm.WindowContainerProto.ORIENTATION;
import static com.android.server.wm.WindowContainerProto.SURFACE_ANIMATOR;
@@ -33,7 +40,9 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.logWithStack;
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
+import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
import android.annotation.CallSuper;
import android.annotation.IntDef;
@@ -45,17 +54,24 @@
import android.graphics.Rect;
import android.os.Debug;
import android.os.IBinder;
+import android.os.Trace;
+import android.util.Pair;
import android.util.Pools;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
+import android.view.DisplayInfo;
import android.view.MagnificationSpec;
+import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Builder;
import android.view.SurfaceSession;
+import android.view.WindowManager;
+import android.view.animation.Animation;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.protolog.common.ProtoLog;
import com.android.server.wm.SurfaceAnimator.Animatable;
import java.io.PrintWriter;
@@ -155,6 +171,29 @@
private final Configuration mTmpConfig = new Configuration();
+ /** Interface for {@link #isAnimating} to check which cases for the container is animating. */
+ public interface AnimationFlags {
+ /**
+ * A bit flag indicates that {@link #isAnimating} should also return {@code true}
+ * even though the container is not yet animating, but the window container or its
+ * relatives as specified by PARENTS or CHILDREN are part of an {@link AppTransition}
+ * that is pending so an animation starts soon.
+ */
+ int TRANSITION = 1;
+
+ /**
+ * A bit flag indicates that {@link #isAnimating} should also check if one of the
+ * ancestors of the container are animating in addition to the container itself.
+ */
+ int PARENTS = 2;
+
+ /**
+ * A bit flag indicates that {@link #isAnimating} should also check if one of the
+ * descendants of the container are animating in addition to the container itself.
+ */
+ int CHILDREN = 4;
+ }
+
/**
* Callback which is triggered while changing the parent, after setting up the surface but
* before asking the parent to assign child layers.
@@ -163,6 +202,47 @@
void onPreAssignChildLayers();
}
+ /**
+ * True if this an AppWindowToken and the activity which created this was launched with
+ * ActivityOptions.setLaunchTaskBehind.
+ *
+ * TODO(b/142617871): We run a special animation when the activity was launched with that
+ * flag, but it's not necessary anymore. Keep the window invisible until the task is explicitly
+ * selected to suppress an animation, and remove this flag.
+ */
+ boolean mLaunchTaskBehind;
+
+ /**
+ * If we are running an animation, this determines the transition type. Must be one of
+ * {@link AppTransition#TransitionFlags}.
+ */
+ int mTransit;
+
+ /**
+ * If we are running an animation, this determines the flags during this animation. Must be a
+ * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
+ */
+ int mTransitFlags;
+
+ /** Whether this container should be boosted at the top of all its siblings. */
+ @VisibleForTesting boolean mNeedsZBoost;
+
+ /** Layer used to constrain the animation to a container's stack bounds. */
+ SurfaceControl mAnimationBoundsLayer;
+
+ /** Whether this container needs to create mAnimationBoundsLayer for cropping animations. */
+ boolean mNeedsAnimationBoundsLayer;
+
+ /**
+ * This gets used during some open/close transitions as well as during a change transition
+ * where it represents the starting-state snapshot.
+ */
+ WindowContainerThumbnail mThumbnail;
+ final Rect mTransitStartRect = new Rect();
+ final Point mTmpPoint = new Point();
+ protected final Rect mTmpRect = new Rect();
+ final Rect mTmpPrevBounds = new Rect();
+
WindowContainer(WindowManagerService wms) {
mWmService = wms;
mPendingTransaction = wms.mTransactionFactory.get();
@@ -348,7 +428,7 @@
parent.mTreeWeight += child.mTreeWeight;
parent = parent.getParent();
}
- onChildPositionChanged();
+ onChildPositionChanged(child);
}
/**
@@ -374,7 +454,7 @@
parent.mTreeWeight -= child.mTreeWeight;
parent = parent.getParent();
}
- onChildPositionChanged();
+ onChildPositionChanged(child);
}
/**
@@ -503,7 +583,7 @@
if (mChildren.peekLast() != child) {
mChildren.remove(child);
mChildren.add(child);
- onChildPositionChanged();
+ onChildPositionChanged(child);
}
if (includingParents && getParent() != null) {
getParent().positionChildAt(POSITION_TOP, this /* child */,
@@ -514,7 +594,7 @@
if (mChildren.peekFirst() != child) {
mChildren.remove(child);
mChildren.addFirst(child);
- onChildPositionChanged();
+ onChildPositionChanged(child);
}
if (includingParents && getParent() != null) {
getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
@@ -528,14 +608,14 @@
// doing this adjustment here and remove any adjustments in the callers.
mChildren.remove(child);
mChildren.add(position, child);
- onChildPositionChanged();
+ onChildPositionChanged(child);
}
}
/**
* Notify that a child's position has changed. Possible changes are adding or removing a child.
*/
- void onChildPositionChanged() { }
+ void onChildPositionChanged(WindowContainer child) { }
/**
* Update override configuration and recalculate full config.
@@ -642,51 +722,78 @@
}
/**
- * @return Whether our own container is running an animation or any child, no matter how deep in
- * the hierarchy, is animating.
+ * @return {@code true} when this container or its related containers are running an
+ * animation, {@code false} otherwise.
+ *
+ * By default this predicate only checks if this container itself is actually running an
+ * animation, but you can extend the check target over its relatives, or relax the condition
+ * so that this can return {@code true} if an animation starts soon by giving a combination
+ * of {@link #AnimationFlags}.
+ *
+ * Note that you can give a combination of bitmask flags to specify targets and condition for
+ * checking animating status.
+ * e.g. {@code isAnimating(TRANSITION | PARENT)} returns {@code true} if either this
+ * container itself or one of its parents is running an animation or waiting for an app
+ * transition.
+ *
+ * Note that TRANSITION propagates to parents and children as well.
+ *
+ * {@see AnimationFlags#TRANSITION}
+ * {@see AnimationFlags#PARENTS}
+ * {@see AnimationFlags#CHILDREN}
*/
- boolean isSelfOrChildAnimating() {
- if (isSelfAnimating()) {
+ final boolean isAnimating(int flags) {
+ if (mSurfaceAnimator.isAnimating()) {
return true;
}
- for (int j = mChildren.size() - 1; j >= 0; j--) {
- final WindowContainer wc = mChildren.get(j);
- if (wc.isSelfOrChildAnimating()) {
+ if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) {
+ return true;
+ }
+ if ((flags & PARENTS) != 0) {
+ final WindowContainer parent = getParent();
+ if (parent != null && parent.isAnimating(flags & ~CHILDREN)) {
return true;
}
}
+ if ((flags & CHILDREN) != 0) {
+ for (int i = 0; i < mChildren.size(); ++i) {
+ final WindowContainer wc = mChildren.get(i);
+ if (wc.isAnimating(flags & ~PARENTS)) {
+ return true;
+ }
+ }
+ }
return false;
}
/**
- * @return Whether our own container is running an animation or our parent is animating. This
- * doesn't consider whether children are animating.
+ * @return {@code true} when the container is waiting the app transition start, {@code false}
+ * otherwise.
*/
- boolean isAnimating() {
-
- // We are animating if we ourselves are animating or if our parent is animating.
- return isSelfAnimating() || mParent != null && mParent.isAnimating();
+ boolean isWaitingForTransitionStart() {
+ return false;
}
/**
- * @return {@code true} if in this subtree of the hierarchy we have an {@link AppWindowToken}
- * that is {@link #isSelfAnimating}; {@code false} otherwise.
+ * @return {@code true} if in this subtree of the hierarchy we have an
+ * {@ode ActivityRecord#isAnimating(TRANSITION)}, {@code false} otherwise.
*/
- boolean isAppAnimating() {
- for (int j = mChildren.size() - 1; j >= 0; j--) {
- final WindowContainer wc = mChildren.get(j);
- if (wc.isAppAnimating()) {
- return true;
- }
- }
- return false;
+ boolean isAppTransitioning() {
+ return forAllActivities(app -> app.isAnimating(TRANSITION));
}
/**
* @return Whether our own container running an animation at the moment.
*/
- boolean isSelfAnimating() {
- return mSurfaceAnimator.isAnimating();
+ final boolean isAnimating() {
+ return isAnimating(0 /* self only */);
+ }
+
+ /**
+ * @return {@code true} if the container is in changing app transition.
+ */
+ boolean isChangingAppTransition() {
+ return false;
}
void sendAppVisibilityToClients() {
@@ -988,10 +1095,13 @@
wrapper.release();
}
- void forAllActivities(Consumer<ActivityRecord> callback) {
+ boolean forAllActivities(ToBooleanFunction<ActivityRecord> callback) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
- mChildren.get(i).forAllActivities(callback);
+ if (mChildren.get(i).forAllActivities(callback)) {
+ return true;
+ }
}
+ return false;
}
void forAllWallpaperWindows(Consumer<WallpaperWindowToken> callback) {
@@ -1011,6 +1121,21 @@
}
}
+ /**
+ * For all tasks at or below this container call the callback.
+ *
+ * @param callback Calls the {@link ToBooleanFunction#apply} method for each task found and
+ * stops the search if {@link ToBooleanFunction#apply} returns {@code true}.
+ */
+ boolean forAllTasks(ToBooleanFunction<Task> callback) {
+ for (int i = mChildren.size() - 1; i >= 0; --i) {
+ if (mChildren.get(i).forAllTasks(callback)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
WindowState getWindow(Predicate<WindowState> callback) {
for (int i = mChildren.size() - 1; i >= 0; --i) {
final WindowState w = mChildren.get(i).getWindow(callback);
@@ -1374,6 +1499,201 @@
return null;
}
+ // TODO: Remove this and use #getBounds() instead once we set an app transition animation
+ // on TaskStack.
+ Rect getAnimationBounds(int appStackClipMode) {
+ return getBounds();
+ }
+
+ /**
+ * Applies the app transition animation according the given the layout properties in the
+ * window hierarchy.
+ *
+ * @param lp The layout parameters of the window.
+ * @param transit The app transition type indicates what kind of transition to be applied.
+ * @param enter Whether the app transition is entering transition or not.
+ * @param isVoiceInteraction Whether the container is participating in voice interaction or not.
+ *
+ * @return {@code true} when the container applied the app transition, {@code false} if the
+ * app transition is disabled or skipped.
+ *
+ * @see #getAnimationAdapter
+ */
+ boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
+ boolean isVoiceInteraction) {
+ if (mWmService.mDisableTransitionAnimation) {
+ ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
+ "applyAnimation: transition animation is disabled or skipped. "
+ + "container=%s", this);
+ cancelAnimation();
+ return false;
+ }
+
+ // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
+ // to animate and it can cause strange artifacts when we unfreeze the display if some
+ // different animation is running.
+ try {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation");
+ if (okToAnimate()) {
+ final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
+ transit, enter, isVoiceInteraction);
+ AnimationAdapter adapter = adapters.first;
+ AnimationAdapter thumbnailAdapter = adapters.second;
+ if (adapter != null) {
+ startAnimation(getPendingTransaction(), adapter, !isVisible());
+ if (adapter.getShowWallpaper()) {
+ mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
+ }
+ if (thumbnailAdapter != null) {
+ mThumbnail.startAnimation(
+ getPendingTransaction(), thumbnailAdapter, !isVisible());
+ }
+ }
+ } else {
+ cancelAnimation();
+ }
+ } finally {
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ }
+
+ return isAnimating();
+ }
+
+ /**
+ * Gets the {@link AnimationAdapter} according the given window layout properties in the window
+ * hierarchy.
+ *
+ * @return The return value will always contain two elements, one for normal animations and the
+ * other for thumbnail animation, both can be {@code null}.
+ *
+ * @See com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord
+ * @See LocalAnimationAdapter
+ */
+ Pair<AnimationAdapter, AnimationAdapter> getAnimationAdapter(WindowManager.LayoutParams lp,
+ int transit, boolean enter, boolean isVoiceInteraction) {
+ final Pair<AnimationAdapter, AnimationAdapter> resultAdapters;
+ final int appStackClipMode = getDisplayContent().mAppTransition.getAppStackClipMode();
+
+ // Separate position and size for use in animators.
+ mTmpRect.set(getAnimationBounds(appStackClipMode));
+ mTmpPoint.set(mTmpRect.left, mTmpRect.top);
+ mTmpRect.offsetTo(0, 0);
+
+ final RemoteAnimationController controller =
+ getDisplayContent().mAppTransition.getRemoteAnimationController();
+ final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
+ && isChangingAppTransition();
+
+ // Delaying animation start isn't compatible with remote animations at all.
+ if (controller != null && !mSurfaceAnimator.isAnimationStartDelayed()) {
+ final RemoteAnimationController.RemoteAnimationRecord adapters =
+ controller.createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
+ (isChanging ? mTransitStartRect : null));
+ resultAdapters = new Pair<>(adapters.mAdapter, adapters.mThumbnailAdapter);
+ } else if (isChanging) {
+ final float durationScale = mWmService.getTransitionAnimationScaleLocked();
+ final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
+ mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
+
+ final AnimationAdapter adapter = new LocalAnimationAdapter(
+ new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect, displayInfo,
+ durationScale, true /* isAppAnimation */, false /* isThumbnail */),
+ getSurfaceAnimationRunner());
+
+ final AnimationAdapter thumbnailAdapter = mThumbnail != null
+ ? new LocalAnimationAdapter(new WindowChangeAnimationSpec(mTransitStartRect,
+ mTmpRect, displayInfo, durationScale, true /* isAppAnimation */,
+ true /* isThumbnail */), getSurfaceAnimationRunner())
+ : null;
+ resultAdapters = new Pair<>(adapter, thumbnailAdapter);
+ mTransit = transit;
+ mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
+ } else {
+ mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
+ final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
+
+ if (a != null) {
+ // Only apply corner radius to animation if we're not in multi window mode.
+ // We don't want rounded corners when in pip or split screen.
+ final float windowCornerRadius = !inMultiWindowMode()
+ ? getDisplayContent().getWindowCornerRadius()
+ : 0;
+ AnimationAdapter adapter = new LocalAnimationAdapter(
+ new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
+ getDisplayContent().mAppTransition.canSkipFirstFrame(),
+ appStackClipMode, true /* isAppAnimation */, windowCornerRadius),
+ getSurfaceAnimationRunner());
+
+ resultAdapters = new Pair<>(adapter, null);
+ mNeedsZBoost = a.getZAdjustment() == Animation.ZORDER_TOP;
+ mTransit = transit;
+ mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
+ } else {
+ resultAdapters = new Pair<>(null, null);
+ }
+ }
+ return resultAdapters;
+ }
+
+ final SurfaceAnimationRunner getSurfaceAnimationRunner() {
+ return mWmService.mSurfaceAnimationRunner;
+ }
+
+ private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
+ boolean isVoiceInteraction) {
+ final DisplayContent displayContent = getDisplayContent();
+ final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+ final int width = displayInfo.appWidth;
+ final int height = displayInfo.appHeight;
+ ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: container=%s", this);
+
+ // Determine the visible rect to calculate the thumbnail clip with
+ // getAnimationFrames.
+ final Rect frame = new Rect(0, 0, width, height);
+ final Rect displayFrame = new Rect(0, 0,
+ displayInfo.logicalWidth, displayInfo.logicalHeight);
+ final Rect insets = new Rect();
+ final Rect stableInsets = new Rect();
+ final Rect surfaceInsets = new Rect();
+ getAnimationFrames(frame, insets, stableInsets, surfaceInsets);
+
+ if (mLaunchTaskBehind) {
+ // Differentiate the two animations. This one which is briefly on the screen
+ // gets the !enter animation, and the other one which remains on the
+ // screen gets the enter animation. Both appear in the mOpeningApps set.
+ enter = false;
+ }
+ ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
+ "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
+ + "surfaceInsets=%s",
+ AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);
+ final Configuration displayConfig = displayContent.getConfiguration();
+ final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
+ displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
+ surfaceInsets, stableInsets, isVoiceInteraction, inFreeformWindowingMode(), this);
+ if (a != null) {
+ if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
+ final int containingWidth = frame.width();
+ final int containingHeight = frame.height();
+ a.initialize(containingWidth, containingHeight, width, height);
+ a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
+ }
+ return a;
+ }
+
+ RemoteAnimationTarget createRemoteAnimationTarget(
+ RemoteAnimationController.RemoteAnimationRecord record) {
+ return null;
+ }
+
+ boolean okToDisplay() {
+ return mDisplayContent != null && mDisplayContent.okToDisplay();
+ }
+
+ boolean okToAnimate() {
+ return mDisplayContent != null && mDisplayContent.okToAnimate();
+ }
+
@Override
public void commitPendingTransaction() {
scheduleAnimation();
@@ -1473,6 +1793,26 @@
return getBounds();
}
+ /**
+ * The {@code outFrame} retrieved by this method specifies where the animation will finish
+ * the entrance animation, as the next frame will display the window at these coordinates. In
+ * case of exit animation, this is where the animation will start, as the frame before the
+ * animation is displaying the window at these bounds.
+ *
+ * @param outFrame The bounds where entrance animation finishes or exit animation starts.
+ * @param outInsets Insets that are covered by system windows.
+ * @param outStableInsets Insets that determine the area covered by the stable system windows.
+ * @param outSurfaceInsets Positive insets between the drawing surface and window content.
+ */
+ void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
+ Rect outSurfaceInsets) {
+ final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
+ outFrame.set(0, 0, displayInfo.appWidth, displayInfo.appHeight);
+ outInsets.setEmpty();
+ outStableInsets.setEmpty();
+ outSurfaceInsets.setEmpty();
+ }
+
void getRelativeDisplayedPosition(Point outPos) {
final Rect dispBounds = getDisplayedBounds();
outPos.set(dispBounds.left, dispBounds.top);
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/WindowContainerThumbnail.java
similarity index 66%
rename from services/core/java/com/android/server/wm/AppWindowThumbnail.java
rename to services/core/java/com/android/server/wm/WindowContainerThumbnail.java
index acd96e9..604eae6 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/WindowContainerThumbnail.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.server.wm;
@@ -19,10 +19,10 @@
import static android.view.SurfaceControl.METADATA_OWNER_UID;
import static android.view.SurfaceControl.METADATA_WINDOW_TYPE;
-import static com.android.server.wm.AppWindowThumbnailProto.HEIGHT;
-import static com.android.server.wm.AppWindowThumbnailProto.SURFACE_ANIMATOR;
-import static com.android.server.wm.AppWindowThumbnailProto.WIDTH;
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.server.wm.WindowContainerThumbnailProto.HEIGHT;
+import static com.android.server.wm.WindowContainerThumbnailProto.SURFACE_ANIMATOR;
+import static com.android.server.wm.WindowContainerThumbnailProto.WIDTH;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
@@ -30,7 +30,7 @@
import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
import android.graphics.Point;
-import android.os.Binder;
+import android.os.Process;
import android.util.proto.ProtoOutputStream;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -44,39 +44,40 @@
import java.util.function.Supplier;
/**
- * Represents a surface that is displayed over an {@link ActivityRecord}
+ * Represents a surface that is displayed over a subclass of {@link WindowContainer}
*/
-class AppWindowThumbnail implements Animatable {
+class WindowContainerThumbnail implements Animatable {
- private static final String TAG = TAG_WITH_CLASS_NAME ? "AppWindowThumbnail" : TAG_WM;
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainerThumbnail" : TAG_WM;
- private final ActivityRecord mActivityRecord;
+ private final WindowContainer mWindowContainer;
private SurfaceControl mSurfaceControl;
private final SurfaceAnimator mSurfaceAnimator;
private final int mWidth;
private final int mHeight;
private final boolean mRelative;
- AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, ActivityRecord activity,
- GraphicBuffer thumbnailHeader) {
- this(surfaceFactory, t, activity, thumbnailHeader, false /* relative */);
+ WindowContainerThumbnail(Supplier<Surface> surfaceFactory, Transaction t,
+ WindowContainer container, GraphicBuffer thumbnailHeader) {
+ this(surfaceFactory, t, container, thumbnailHeader, false /* relative */);
}
/**
* @param t Transaction to create the thumbnail in.
- * @param activity {@link ActivityRecord} to associate this thumbnail with.
+ * @param container The sub-class of {@link WindowContainer} to associate this thumbnail with.
* @param thumbnailHeader A thumbnail or placeholder for thumbnail to initialize with.
- * @param relative Whether this thumbnail will be a child of activity (and thus positioned
+ * @param relative Whether this thumbnail will be a child of the container (and thus positioned
* relative to it) or not.
*/
- AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, ActivityRecord activity,
- GraphicBuffer thumbnailHeader, boolean relative) {
- this(t, activity, thumbnailHeader, relative, surfaceFactory.get(), null);
+ WindowContainerThumbnail(Supplier<Surface> surfaceFactory, Transaction t,
+ WindowContainer container, GraphicBuffer thumbnailHeader, boolean relative) {
+ this(t, container, thumbnailHeader, relative, surfaceFactory.get(), null);
}
- AppWindowThumbnail(Transaction t, ActivityRecord activity, GraphicBuffer thumbnailHeader,
- boolean relative, Surface drawSurface, SurfaceAnimator animator) {
- mActivityRecord = activity;
+ WindowContainerThumbnail(Transaction t, WindowContainer container,
+ GraphicBuffer thumbnailHeader, boolean relative, Surface drawSurface,
+ SurfaceAnimator animator) {
+ mWindowContainer = container;
mRelative = relative;
if (animator != null) {
mSurfaceAnimator = animator;
@@ -84,24 +85,21 @@
// We can't use a delegating constructor since we need to
// reference this::onAnimationFinished
mSurfaceAnimator =
- new SurfaceAnimator(this, this::onAnimationFinished, activity.mWmService);
+ new SurfaceAnimator(this, this::onAnimationFinished, container.mWmService);
}
mWidth = thumbnailHeader.getWidth();
mHeight = thumbnailHeader.getHeight();
// Create a new surface for the thumbnail
- WindowState window = mActivityRecord.findMainWindow();
-
// TODO: This should be attached as a child to the app token, once the thumbnail animations
// use relative coordinates. Once we start animating task we can also consider attaching
// this to the task.
- mSurfaceControl = mActivityRecord.makeSurface()
- .setName("thumbnail anim: " + mActivityRecord.toString())
+ mSurfaceControl = mWindowContainer.makeSurface()
+ .setName("thumbnail anim: " + mWindowContainer.toString())
.setBufferSize(mWidth, mHeight)
.setFormat(PixelFormat.TRANSLUCENT)
- .setMetadata(METADATA_WINDOW_TYPE, mActivityRecord.windowType)
- .setMetadata(METADATA_OWNER_UID,
- window != null ? window.mOwnerUid : Binder.getCallingUid())
+ .setMetadata(METADATA_WINDOW_TYPE, mWindowContainer.getWindowingMode())
+ .setMetadata(METADATA_OWNER_UID, Process.myUid())
.build();
ProtoLog.i(WM_SHOW_TRANSACTIONS, " THUMBNAIL %s: CREATE", mSurfaceControl);
@@ -112,11 +110,11 @@
drawSurface.release();
t.show(mSurfaceControl);
- // We parent the thumbnail to the task, and just place it on top of anything else in the
- // task.
+ // We parent the thumbnail to the container, and just place it on top of anything else in
+ // the container.
t.setLayer(mSurfaceControl, Integer.MAX_VALUE);
if (relative) {
- t.reparent(mSurfaceControl, mActivityRecord.getSurfaceControl());
+ t.reparent(mSurfaceControl, mWindowContainer.getSurfaceControl());
}
}
@@ -126,12 +124,12 @@
void startAnimation(Transaction t, Animation anim, Point position) {
anim.restrictDuration(MAX_ANIMATION_DURATION);
- anim.scaleCurrentDuration(mActivityRecord.mWmService.getTransitionAnimationScaleLocked());
+ anim.scaleCurrentDuration(mWindowContainer.mWmService.getTransitionAnimationScaleLocked());
mSurfaceAnimator.startAnimation(t, new LocalAnimationAdapter(
new WindowAnimationSpec(anim, position,
- mActivityRecord.getDisplayContent().mAppTransition.canSkipFirstFrame(),
- mActivityRecord.getDisplayContent().getWindowCornerRadius()),
- mActivityRecord.mWmService.mSurfaceAnimationRunner), false /* hidden */);
+ mWindowContainer.getDisplayContent().mAppTransition.canSkipFirstFrame(),
+ mWindowContainer.getDisplayContent().getWindowCornerRadius()),
+ mWindowContainer.mWmService.mSurfaceAnimationRunner), false /* hidden */);
}
/**
@@ -161,10 +159,11 @@
/**
* Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
- * com.android.server.wm.AppWindowThumbnailProto}.
+ * com.android.server.wm.WindowContainerThumbnailProto}.
*
- * @param proto Stream to write the AppWindowThumbnail object to.
- * @param fieldId Field Id of the AppWindowThumbnail as defined in the parent message.
+ * @param proto Stream to write the WindowContainerThumbnailProto object to.
+ * @param fieldId Field Id of the WindowContainerThumbnailProto as defined in the parent
+ * message.
* @hide
*/
void writeToProto(ProtoOutputStream proto, long fieldId) {
@@ -179,19 +178,19 @@
@Override
public Transaction getPendingTransaction() {
- return mActivityRecord.getPendingTransaction();
+ return mWindowContainer.getPendingTransaction();
}
@Override
public void commitPendingTransaction() {
- mActivityRecord.commitPendingTransaction();
+ mWindowContainer.commitPendingTransaction();
}
@Override
public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
t.setLayer(leash, Integer.MAX_VALUE);
if (mRelative) {
- t.reparent(leash, mActivityRecord.getSurfaceControl());
+ t.reparent(leash, mWindowContainer.getSurfaceControl());
}
}
@@ -205,7 +204,7 @@
@Override
public Builder makeAnimationLeash() {
- return mActivityRecord.makeSurface();
+ return mWindowContainer.makeSurface();
}
@Override
@@ -215,12 +214,12 @@
@Override
public SurfaceControl getAnimationLeashParent() {
- return mActivityRecord.getAppAnimationLayer();
+ return mWindowContainer.getAnimationLeashParent();
}
@Override
public SurfaceControl getParentSurfaceControl() {
- return mActivityRecord.getParentSurfaceControl();
+ return mWindowContainer.getParentSurfaceControl();
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 085b0f6..2c56b11 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -94,6 +94,9 @@
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
import static com.android.server.wm.ProtoLogGroup.WM_ERROR;
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
+import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
@@ -2418,7 +2421,7 @@
if (win.isWinVisibleLw() && winAnimator.applyAnimationLocked(transit, false)) {
focusMayChange = true;
win.mAnimatingExit = true;
- } else if (win.isAnimating()) {
+ } else if (win.isAnimating(TRANSITION | PARENTS)) {
// Currently in a hide animation... turn this into
// an exit.
win.mAnimatingExit = true;
@@ -4358,7 +4361,7 @@
final DisplayContent topFocusedDisplay = mRoot.getTopFocusedDisplayContent();
final ActivityRecord focusedApp = topFocusedDisplay.mFocusedApp;
return (focusedApp != null && focusedApp.getTask() != null)
- ? focusedApp.getTask().mStack : null;
+ ? focusedApp.getTask().getTaskStack() : null;
}
public boolean detectSafeMode() {
@@ -7618,7 +7621,7 @@
private void waitForAnimationsToComplete() {
synchronized (mGlobalLock) {
long timeoutRemaining = ANIMATION_COMPLETED_TIMEOUT_MS;
- while (mRoot.isSelfOrChildAnimating() && timeoutRemaining > 0) {
+ while (mRoot.isAnimating(TRANSITION | CHILDREN) && timeoutRemaining > 0) {
long startTime = System.currentTimeMillis();
try {
mGlobalLock.wait(timeoutRemaining);
@@ -7627,7 +7630,7 @@
timeoutRemaining -= (System.currentTimeMillis() - startTime);
}
- if (mRoot.isSelfOrChildAnimating()) {
+ if (mRoot.isAnimating(TRANSITION | CHILDREN)) {
Log.w(TAG, "Timed out waiting for animations to complete.");
}
}
@@ -7654,7 +7657,7 @@
return;
}
- final TaskStack stack = task.mStack;
+ final TaskStack stack = task.getTaskStack();
// We ignore home stack since we don't want home stack to move to front when touched.
// Specifically, in freeform we don't want tapping on home to cause the freeform apps to go
// behind home. See b/117376413
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f0ea13d..d196c34 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -98,6 +98,8 @@
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RESIZE;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
+import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
@@ -636,7 +638,7 @@
private boolean mIsDimming = false;
private @Nullable InsetsSourceProvider mControllableInsetProvider;
- private InsetsState mClientInsetsState = new InsetsState();
+ private InsetsState mClientInsetsState;
private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
private KeyInterceptionInfo mKeyInterceptionInfo;
@@ -765,6 +767,8 @@
mSeq = seq;
mPowerManagerWrapper = powerManagerWrapper;
mForceSeamlesslyRotate = token.mRoundedCornerOverlay;
+ mClientInsetsState =
+ getDisplayContent().getInsetsStateController().getInsetsForDispatch(this);
if (DEBUG) {
Slog.v(TAG, "Window " + this + " client=" + c.asBinder()
+ " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
@@ -1279,7 +1283,7 @@
// notify the client of frame changes in this case. Not only is it a lot of churn, but
// the frame may not correspond to the surface size or the onscreen area at various
// phases in the animation, and the client will become sad and confused.
- if (task != null && task.mStack.isAnimatingBounds()) {
+ if (task != null && task.getTaskStack().isAnimatingBounds()) {
return;
}
@@ -1419,8 +1423,8 @@
TaskStack getStack() {
Task task = getTask();
if (task != null) {
- if (task.mStack != null) {
- return task.mStack;
+ if (task.getTaskStack() != null) {
+ return task.getTaskStack();
}
}
// Some system windows (e.g. "Power off" dialog) don't have a task, but we would still
@@ -1439,7 +1443,7 @@
bounds.setEmpty();
mTmpRect.setEmpty();
if (intersectWithStackBounds) {
- final TaskStack stack = task.mStack;
+ final TaskStack stack = task.getTaskStack();
if (stack != null) {
stack.getDimBounds(mTmpRect);
} else {
@@ -1492,7 +1496,8 @@
@Override
boolean hasContentToDisplay() {
if (!mAppFreezing && isDrawnLw() && (mViewVisibility == View.VISIBLE
- || (isAnimating() && !getDisplayContent().mAppTransition.isTransitionSet()))) {
+ || (isAnimating(TRANSITION | PARENTS)
+ && !getDisplayContent().mAppTransition.isTransitionSet()))) {
return true;
}
@@ -1550,8 +1555,8 @@
*/
// TODO: Can we consolidate this with #isVisible() or have a more appropriate name for this?
boolean isWinVisibleLw() {
- return (mActivityRecord == null || !mActivityRecord.hiddenRequested || mActivityRecord.isSelfAnimating())
- && isVisible();
+ return (mActivityRecord == null || !mActivityRecord.hiddenRequested
+ || mActivityRecord.isAnimating(TRANSITION)) && isVisible();
}
/**
@@ -1597,9 +1602,9 @@
final ActivityRecord atoken = mActivityRecord;
if (atoken != null) {
return ((!isParentWindowHidden() && !atoken.hiddenRequested)
- || isAnimating());
+ || isAnimating(TRANSITION | PARENTS));
}
- return !isParentWindowHidden() || isAnimating();
+ return !isParentWindowHidden() || isAnimating(TRANSITION | PARENTS);
}
/**
@@ -1634,7 +1639,7 @@
final boolean parentAndClientVisible = !isParentWindowHidden()
&& mViewVisibility == View.VISIBLE && !mToken.isHidden();
return mHasSurface && isVisibleByPolicy() && !mDestroying
- && (parentAndClientVisible || isAnimating());
+ && (parentAndClientVisible || isAnimating(TRANSITION | PARENTS));
}
// TODO: Another visibility method that was added late in the release to minimize risk.
@@ -1664,7 +1669,7 @@
final ActivityRecord atoken = mActivityRecord;
return isDrawnLw() && isVisibleByPolicy()
&& ((!isParentWindowHidden() && (atoken == null || !atoken.hiddenRequested))
- || isAnimating());
+ || isAnimating(TRANSITION | PARENTS));
}
/**
@@ -1672,7 +1677,7 @@
*/
@Override
public boolean isAnimatingLw() {
- return isAnimating();
+ return isAnimating(TRANSITION | PARENTS);
}
@Override
@@ -1718,7 +1723,7 @@
// to determine if it's occluding apps.
return ((!mIsWallpaper && mAttrs.format == PixelFormat.OPAQUE)
|| (mIsWallpaper && mWallpaperVisible))
- && isDrawnLw() && !isAnimating();
+ && isDrawnLw() && !isAnimating(TRANSITION | PARENTS);
}
@Override
@@ -1740,7 +1745,7 @@
// Starting window that's exiting will be removed when the animation finishes.
// Mark all relevant flags for that onExitAnimationDone will proceed all the way
// to actually remove it.
- if (!visible && isVisibleNow() && mActivityRecord.isSelfAnimating()) {
+ if (!visible && isVisibleNow() && mActivityRecord.isAnimating(TRANSITION)) {
mAnimatingExit = true;
mRemoveOnExit = true;
mWindowRemovalAllowed = true;
@@ -1840,8 +1845,8 @@
final int top = mWindowFrames.mFrame.top;
final Task task = getTask();
final boolean adjustedForMinimizedDockOrIme = task != null
- && (task.mStack.isAdjustedForMinimizedDockedStack()
- || task.mStack.isAdjustedForIme());
+ && (task.getTaskStack().isAdjustedForMinimizedDockedStack()
+ || task.getTaskStack().isAdjustedForIme());
if (mToken.okToAnimate()
&& (mAttrs.privateFlags & PRIVATE_FLAG_NO_MOVE_ANIMATION) == 0
&& !isDragResizing() && !adjustedForMinimizedDockOrIme
@@ -1877,7 +1882,7 @@
boolean isObscuringDisplay() {
Task task = getTask();
- if (task != null && task.mStack != null && !task.mStack.fillsParent()) {
+ if (task != null && task.getTaskStack() != null && !task.getTaskStack().fillsParent()) {
return false;
}
return isOpaqueDrawn() && fillsDisplay();
@@ -2013,12 +2018,12 @@
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
"Remove %s: mSurfaceController=%s mAnimatingExit=%b mRemoveOnExit=%b "
+ "mHasSurface=%b surfaceShowing=%b animating=%b app-animation=%b "
- + "mWillReplaceWindow=%b inPendingTransaction=%b mDisplayFrozen=%b "
- + "callers=%s",
+ + "mWillReplaceWindow=%b mDisplayFrozen=%b callers=%s",
this, mWinAnimator.mSurfaceController, mAnimatingExit, mRemoveOnExit,
- mHasSurface, mWinAnimator.getShown(), isAnimating(),
- mActivityRecord != null && mActivityRecord.isSelfAnimating(), mWillReplaceWindow,
- mActivityRecord != null && mActivityRecord.inPendingTransaction,
+ mHasSurface, mWinAnimator.getShown(),
+ isAnimating(TRANSITION | PARENTS),
+ mActivityRecord != null && mActivityRecord.isAnimating(TRANSITION),
+ mWillReplaceWindow,
mWmService.mDisplayFrozen, Debug.getCallers(6));
// Visibility of the removed window. Will be used later to update orientation later on.
@@ -2076,7 +2081,7 @@
mWmService.mAccessibilityController.onWindowTransitionLocked(this, transit);
}
}
- final boolean isAnimating = isAnimating()
+ final boolean isAnimating = isAnimating(TRANSITION | PARENTS)
&& (mActivityRecord == null || !mActivityRecord.isWaitingForTransitionStart());
final boolean lastWindowIsStartingWindow = startingWindow && mActivityRecord != null
&& mActivityRecord.isLastWindow(this);
@@ -2204,7 +2209,6 @@
mInputChannel = inputChannels[0];
mClientChannel = inputChannels[1];
mWmService.mInputManager.registerInputChannel(mInputChannel);
- mClientChannel.setToken(mInputChannel.getToken());
mInputWindowHandle.token = mInputChannel.getToken();
if (outInputChannel != null) {
mClientChannel.transferTo(outInputChannel);
@@ -2297,8 +2301,8 @@
void applyAdjustForImeIfNeeded() {
final Task task = getTask();
- if (task != null && task.mStack != null && task.mStack.isAdjustedForIme()) {
- task.mStack.applyAdjustForImeIfNeeded(task);
+ if (task != null && task.getTaskStack() != null && task.getTaskStack().isAdjustedForIme()) {
+ task.getTaskStack().applyAdjustForImeIfNeeded(task);
}
}
@@ -2629,7 +2633,7 @@
return false;
}
- return mActivityRecord.getTask().mStack.shouldIgnoreInput()
+ return mActivityRecord.getTask().getTaskStack().shouldIgnoreInput()
|| mActivityRecord.hiddenRequested
|| isAnimatingToRecents();
}
@@ -2683,10 +2687,11 @@
if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
if (doAnimation) {
if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
- + isLegacyPolicyVisibility() + " animating=" + isAnimating());
+ + isLegacyPolicyVisibility()
+ + " animating=" + isAnimating(TRANSITION | PARENTS));
if (!mToken.okToAnimate()) {
doAnimation = false;
- } else if (isLegacyPolicyVisibility() && !isAnimating()) {
+ } else if (isLegacyPolicyVisibility() && !isAnimating(TRANSITION | PARENTS)) {
// Check for the case where we are currently visible and
// not animating; we do not want to do animation at such a
// point to become visible when we already are.
@@ -2726,7 +2731,7 @@
}
if (doAnimation) {
mWinAnimator.applyAnimationLocked(TRANSIT_EXIT, false);
- if (!isAnimating()) {
+ if (!isAnimating(TRANSITION | PARENTS)) {
doAnimation = false;
}
}
@@ -3148,7 +3153,7 @@
return;
}
- final TaskStack stack = task.mStack;
+ final TaskStack stack = task.getTaskStack();
if (stack == null) {
return;
}
@@ -3162,7 +3167,7 @@
return;
}
- final TaskStack stack = task.mStack;
+ final TaskStack stack = task.getTaskStack();
if (stack == null) {
return;
}
@@ -4163,9 +4168,9 @@
+ " tok.hiddenRequested="
+ (mActivityRecord != null && mActivityRecord.hiddenRequested)
+ " tok.hidden=" + (mActivityRecord != null && mActivityRecord.isHidden())
- + " animating=" + isAnimating()
+ + " animating=" + isAnimating(TRANSITION | PARENTS)
+ " tok animating="
- + (mActivityRecord != null && mActivityRecord.isSelfAnimating())
+ + (mActivityRecord != null && mActivityRecord.isAnimating(TRANSITION))
+ " Callers=" + Debug.getCallers(4));
}
}
@@ -4392,7 +4397,7 @@
void onExitAnimationDone() {
if (DEBUG_ANIM) Slog.v(TAG, "onExitAnimationDone in " + this
+ ": exiting=" + mAnimatingExit + " remove=" + mRemoveOnExit
- + " selfAnimating=" + isSelfAnimating());
+ + " selfAnimating=" + isAnimating());
if (!mChildren.isEmpty()) {
// Copying to a different list as multiple children can be removed.
@@ -4415,7 +4420,7 @@
}
}
- if (isSelfAnimating()) {
+ if (isAnimating()) {
return;
}
if (mWmService.mAccessibilityController != null) {
@@ -4563,25 +4568,25 @@
}
if (DEBUG_VISIBILITY) {
Slog.v(TAG, "Win " + this + ": isDrawn=" + isDrawnLw()
- + ", animating=" + isAnimating());
+ + ", animating=" + isAnimating(TRANSITION | PARENTS));
if (!isDrawnLw()) {
Slog.v(TAG, "Not displayed: s=" + mWinAnimator.mSurfaceController
+ " pv=" + isVisibleByPolicy()
+ " mDrawState=" + mWinAnimator.mDrawState
+ " ph=" + isParentWindowHidden()
+ " th=" + (mActivityRecord != null ? mActivityRecord.hiddenRequested : false)
- + " a=" + isAnimating());
+ + " a=" + isAnimating(TRANSITION | PARENTS));
}
}
results.numInteresting++;
if (isDrawnLw()) {
results.numDrawn++;
- if (!isAnimating()) {
+ if (!isAnimating(TRANSITION | PARENTS)) {
results.numVisible++;
}
results.nowGone = false;
- } else if (isAnimating()) {
+ } else if (isAnimating(TRANSITION | PARENTS)) {
results.nowGone = false;
}
}
@@ -4718,7 +4723,7 @@
+ mRemoveOnExit + ", mDestroying=" + mDestroying);
// Cancel the existing exit animation for the next enter animation.
- if (isSelfAnimating()) {
+ if (isAnimating()) {
cancelAnimation();
destroySurfaceUnchecked();
}
@@ -5398,4 +5403,29 @@
}
return mKeyInterceptionInfo;
}
+
+ @Override
+ void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
+ Rect outSurfaceInsets) {
+ // Containing frame will usually cover the whole screen, including dialog windows.
+ // For freeform workspace windows it will not cover the whole screen and it also
+ // won't exactly match the final freeform window frame (e.g. when overlapping with
+ // the status bar). In that case we need to use the final frame.
+ if (inFreeformWindowingMode()) {
+ outFrame.set(getFrameLw());
+ } else if (isLetterboxedAppWindow()) {
+ outFrame.set(getTask().getBounds());
+ } else if (isDockedResizing()) {
+ // If we are animating while docked resizing, then use the stack bounds as the
+ // animation target (which will be different than the task bounds)
+ outFrame.set(getTask().getParent().getBounds());
+ } else {
+ outFrame.set(getContainingFrame());
+ }
+ outSurfaceInsets.set(getAttrs().surfaceInsets);
+ // TODO(b/72757033): These are insets relative to the window frame, but we're really
+ // interested in the insets relative to the frame we chose in the if-blocks above.
+ getContentInsets(outInsets);
+ getStableInsets(outStableInsets);
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 3f25f89..a853828 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -32,6 +32,8 @@
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
@@ -435,7 +437,7 @@
return;
}
- if (!mWin.mActivityRecord.isSelfAnimating()) {
+ if (!mWin.mActivityRecord.isAnimating(TRANSITION)) {
mWin.mActivityRecord.clearAllDrawn();
} else {
// Currently animating, persist current state of allDrawn until animation
@@ -890,10 +892,10 @@
int posX = 0;
int posY = 0;
- task.mStack.getDimBounds(mTmpStackBounds);
+ task.getTaskStack().getDimBounds(mTmpStackBounds);
boolean allowStretching = false;
- task.mStack.getFinalAnimationSourceHintBounds(mTmpSourceBounds);
+ task.getTaskStack().getFinalAnimationSourceHintBounds(mTmpSourceBounds);
// If we don't have source bounds, we can attempt to use the content insets
// in the following scenario:
// 1. We have content insets.
@@ -903,8 +905,8 @@
// because of the force-scale until resize state.
if (mTmpSourceBounds.isEmpty() && (mWin.mLastRelayoutContentInsets.width() > 0
|| mWin.mLastRelayoutContentInsets.height() > 0)
- && !task.mStack.lastAnimatingBoundsWasToFullscreen()) {
- mTmpSourceBounds.set(task.mStack.mPreAnimationBounds);
+ && !task.getTaskStack().lastAnimatingBoundsWasToFullscreen()) {
+ mTmpSourceBounds.set(task.getTaskStack().mPreAnimationBounds);
mTmpSourceBounds.inset(mWin.mLastRelayoutContentInsets);
allowStretching = true;
}
@@ -918,7 +920,7 @@
if (!mTmpSourceBounds.isEmpty()) {
// Get the final target stack bounds, if we are not animating, this is just the
// current stack bounds
- task.mStack.getFinalAnimationBounds(mTmpAnimatingBounds);
+ task.getTaskStack().getFinalAnimationBounds(mTmpAnimatingBounds);
// Calculate the current progress and interpolate the difference between the target
// and source bounds
@@ -1169,7 +1171,7 @@
w.mToken.hasVisible = true;
}
} else {
- if (DEBUG_ANIM && mWin.isAnimating()) {
+ if (DEBUG_ANIM && mWin.isAnimating(TRANSITION | PARENTS)) {
Slog.v(TAG, "prepareSurface: No changes in animation for " + this);
}
displayed = true;
@@ -1332,7 +1334,7 @@
* @return true if an animation has been loaded.
*/
boolean applyAnimationLocked(int transit, boolean isEntrance) {
- if (mWin.isSelfAnimating() && mAnimationIsEntrance == isEntrance) {
+ if (mWin.isAnimating() && mAnimationIsEntrance == isEntrance) {
// If we are trying to apply an animation, but already running
// an animation of the same type, then just leave that one alone.
return true;
@@ -1400,7 +1402,7 @@
mWin.getDisplayContent().adjustForImeIfNeeded();
}
- return mWin.isAnimating();
+ return mWin.isAnimating(TRANSITION | PARENTS);
}
void writeToProto(ProtoOutputStream proto, long fieldId) {
@@ -1497,7 +1499,7 @@
*/
boolean isForceScaled() {
final Task task = mWin.getTask();
- if (task != null && task.mStack.isForceScaled()) {
+ if (task != null && task.getTaskStack().isForceScaled()) {
return true;
}
return mForceScaleUntilResize;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index ad71237..88a1458 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -22,6 +22,9 @@
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
+import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
+import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
@@ -159,13 +162,10 @@
final int count = mChildren.size();
boolean changed = false;
- boolean delayed = false;
+ final boolean delayed = isAnimating(TRANSITION | PARENTS | CHILDREN);
for (int i = 0; i < count; i++) {
final WindowState win = mChildren.get(i);
- if (win.isAnimating()) {
- delayed = true;
- }
changed |= win.onSetAppExiting();
}
@@ -321,14 +321,6 @@
return toString();
}
- boolean okToDisplay() {
- return mDisplayContent != null && mDisplayContent.okToDisplay();
- }
-
- boolean okToAnimate() {
- return mDisplayContent != null && mDisplayContent.okToAnimate();
- }
-
/**
* Return whether windows from this token can layer above the
* system bars, or in other words extend outside of the "Decor Frame"
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index bcd1713..425b4b6 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -23,7 +23,6 @@
"com_android_server_AlarmManagerService.cpp",
"com_android_server_am_BatteryStatsService.cpp",
"com_android_server_connectivity_Vpn.cpp",
- "com_android_server_connectivity_tethering_OffloadHardwareInterface.cpp",
"com_android_server_ConsumerIrService.cpp",
"com_android_server_devicepolicy_CryptoTestHelper.cpp",
"com_android_server_HardwarePropertiesManagerService.cpp",
@@ -54,6 +53,7 @@
"com_android_server_am_LowMemDetector.cpp",
"onload.cpp",
":lib_networkStatsFactory_native",
+ ":tethering-jni-srcs",
],
include_dirs: [
@@ -147,6 +147,7 @@
"android.frameworks.sensorservice@1.0",
"android.system.suspend@1.0",
"suspend_control_aidl_interface-cpp",
+ "vintf-vibrator-cpp",
],
static_libs: [
diff --git a/services/core/jni/com_android_server_VibratorService.cpp b/services/core/jni/com_android_server_VibratorService.cpp
index 64c7935..51bea1f 100644
--- a/services/core/jni/com_android_server_VibratorService.cpp
+++ b/services/core/jni/com_android_server_VibratorService.cpp
@@ -17,6 +17,9 @@
#define LOG_TAG "VibratorService"
#include <android/hardware/vibrator/1.4/IVibrator.h>
+#include <android/hardware/vibrator/BnVibratorCallback.h>
+#include <android/hardware/vibrator/IVibrator.h>
+#include <binder/IServiceManager.h>
#include "jni.h"
#include <nativehelper/JNIHelp.h>
@@ -41,11 +44,155 @@
namespace V1_2 = android::hardware::vibrator::V1_2;
namespace V1_3 = android::hardware::vibrator::V1_3;
namespace V1_4 = android::hardware::vibrator::V1_4;
+namespace aidl = android::hardware::vibrator;
namespace android {
static jmethodID sMethodIdOnComplete;
+// TODO(b/141828236): remove HIDL 1.4 and re-write all of this code to remove
+// shim
+class VibratorShim : public V1_4::IVibrator {
+ public:
+ VibratorShim(const sp<aidl::IVibrator>& vib) : mVib(vib) {}
+
+ Return<V1_0::Status> on(uint32_t timeoutMs) override {
+ return on_1_4(timeoutMs, nullptr);
+ }
+
+ Return<V1_0::Status> off() override {
+ return toHidlStatus(mVib->off());
+ }
+
+ Return<bool> supportsAmplitudeControl() override {
+ int32_t cap = 0;
+ if (!mVib->getCapabilities(&cap).isOk()) return false;
+ return (cap & aidl::IVibrator::CAP_AMPLITUDE_CONTROL) > 0;
+ }
+
+ Return<V1_0::Status> setAmplitude(uint8_t amplitude) override {
+ return toHidlStatus(mVib->setAmplitude(amplitude));
+ }
+
+ Return<void> perform(V1_0::Effect effect, V1_0::EffectStrength strength,
+ perform_cb _hidl_cb) override {
+ return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb);
+ }
+
+ Return<void> perform_1_1(V1_1::Effect_1_1 effect, V1_0::EffectStrength strength,
+ perform_1_1_cb _hidl_cb) override {
+ return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb);
+ }
+
+ Return<void> perform_1_2(V1_2::Effect effect, V1_0::EffectStrength strength,
+ perform_1_2_cb _hidl_cb) override {
+ return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb);
+ }
+
+ Return<bool> supportsExternalControl() override {
+ int32_t cap = 0;
+ if (!mVib->getCapabilities(&cap).isOk()) return false;
+ return (cap & aidl::IVibrator::CAP_EXTERNAL_CONTROL) > 0;
+ }
+
+ Return<V1_0::Status> setExternalControl(bool enabled) override {
+ return toHidlStatus(mVib->setExternalControl(enabled));
+ }
+
+ Return<void> perform_1_3(V1_3::Effect effect, V1_0::EffectStrength strength,
+ perform_1_3_cb _hidl_cb) override {
+ return perform_1_4(static_cast<V1_3::Effect>(effect), strength, nullptr, _hidl_cb);
+ }
+
+ Return<uint32_t> getCapabilities() override {
+ static_assert(static_cast<int32_t>(V1_4::Capabilities::ON_COMPLETION_CALLBACK) ==
+ static_cast<int32_t>(aidl::IVibrator::CAP_ON_CALLBACK));
+ static_assert(static_cast<int32_t>(V1_4::Capabilities::PERFORM_COMPLETION_CALLBACK) ==
+ static_cast<int32_t>(aidl::IVibrator::CAP_PERFORM_CALLBACK));
+
+ int32_t cap;
+ if (!mVib->getCapabilities(&cap).isOk()) return 0;
+ return (cap & (aidl::IVibrator::CAP_ON_CALLBACK |
+ aidl::IVibrator::CAP_PERFORM_CALLBACK)) > 0;
+ }
+
+ Return<V1_0::Status> on_1_4(uint32_t timeoutMs,
+ const sp<V1_4::IVibratorCallback>& callback) override {
+ sp<aidl::IVibratorCallback> cb = callback ? new CallbackShim(callback) : nullptr;
+ return toHidlStatus(mVib->on(timeoutMs, cb));
+ }
+
+ Return<void> perform_1_4(V1_3::Effect effect, V1_0::EffectStrength strength,
+ const sp<V1_4::IVibratorCallback>& callback,
+ perform_1_4_cb _hidl_cb) override {
+ static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) ==
+ static_cast<uint8_t>(aidl::EffectStrength::LIGHT));
+ static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) ==
+ static_cast<uint8_t>(aidl::EffectStrength::MEDIUM));
+ static_assert(static_cast<uint8_t>(V1_0::EffectStrength::STRONG) ==
+ static_cast<uint8_t>(aidl::EffectStrength::STRONG));
+ static_assert(static_cast<uint8_t>(V1_3::Effect::CLICK) ==
+ static_cast<uint8_t>(aidl::Effect::CLICK));
+ static_assert(static_cast<uint8_t>(V1_3::Effect::DOUBLE_CLICK) ==
+ static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK));
+ static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) ==
+ static_cast<uint8_t>(aidl::Effect::TICK));
+ static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) ==
+ static_cast<uint8_t>(aidl::Effect::THUD));
+ static_assert(static_cast<uint8_t>(V1_3::Effect::POP) ==
+ static_cast<uint8_t>(aidl::Effect::POP));
+ static_assert(static_cast<uint8_t>(V1_3::Effect::HEAVY_CLICK) ==
+ static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK));
+ static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_1) ==
+ static_cast<uint8_t>(aidl::Effect::RINGTONE_1));
+ static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_2) ==
+ static_cast<uint8_t>(aidl::Effect::RINGTONE_2));
+ static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) ==
+ static_cast<uint8_t>(aidl::Effect::RINGTONE_15));
+ static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) ==
+ static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK));
+
+ sp<aidl::IVibratorCallback> cb = callback ? new CallbackShim(callback) : nullptr;
+ int timeoutMs = 0;
+ Return<V1_0::Status> status = toHidlStatus(
+ mVib->perform(static_cast<aidl::Effect>(effect),
+ static_cast<aidl::EffectStrength>(strength), cb, &timeoutMs));
+
+ if (status.isOk()) {
+ _hidl_cb(status, timeoutMs);
+ return android::hardware::Status::ok();
+ } else {
+ return android::hardware::details::StatusOf<V1_0::Status, void>(status);
+ }
+ }
+ private:
+ sp<aidl::IVibrator> mVib;
+
+ Return<V1_0::Status> toHidlStatus(const android::binder::Status& status) {
+ switch(status.exceptionCode()) {
+ using android::hardware::Status;
+ case Status::EX_NONE: return V1_0::Status::OK;
+ case Status::EX_ILLEGAL_ARGUMENT: return V1_0::Status::BAD_VALUE;
+ case Status::EX_UNSUPPORTED_OPERATION: return V1_0::Status::UNSUPPORTED_OPERATION;
+ case Status::EX_TRANSACTION_FAILED: {
+ return Status::fromStatusT(status.transactionError());
+ }
+ }
+ return V1_0::Status::UNKNOWN_ERROR;
+ }
+
+ class CallbackShim : public aidl::BnVibratorCallback {
+ public:
+ CallbackShim(const sp<V1_4::IVibratorCallback>& cb) : mCb(cb) {}
+ binder::Status onComplete() {
+ mCb->onComplete();
+ return binder::Status::ok(); // oneway, local call
+ }
+ private:
+ sp<V1_4::IVibratorCallback> mCb;
+ };
+};
+
class VibratorCallback : public V1_4::IVibratorCallback {
public:
VibratorCallback(JNIEnv *env, jobject vibration) :
@@ -79,6 +226,11 @@
class HalWrapper {
public:
static std::unique_ptr<HalWrapper> Create() {
+ sp<aidl::IVibrator> aidlVib = waitForVintfService<aidl::IVibrator>();
+ if (aidlVib) {
+ return std::unique_ptr<HalWrapper>(new HalWrapper(new VibratorShim(aidlVib)));
+ }
+
// Assume that if getService returns a nullptr, HAL is not available on the
// device.
auto hal = I::getService();
@@ -103,8 +255,14 @@
}
ALOGE("Failed to issue command to vibrator HAL. Retrying.");
+
// Restoring connection to the HAL.
- mHal = I::tryGetService();
+ sp<aidl::IVibrator> aidlVib = checkVintfService<aidl::IVibrator>();
+ if (aidlVib) {
+ mHal = new VibratorShim(aidlVib);
+ } else {
+ mHal = I::tryGetService();
+ }
}
return ret;
}
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index dd2629d..b546a1d 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -709,6 +709,18 @@
checkAndClearExceptionFromCallback(env, "notifyConfigurationChanged");
}
+static jobject getInputApplicationHandleObjLocalRef(JNIEnv* env,
+ const sp<InputApplicationHandle>& inputApplicationHandle) {
+ if (inputApplicationHandle == nullptr) {
+ return nullptr;
+ }
+ NativeInputApplicationHandle* handle =
+ static_cast<NativeInputApplicationHandle*>(inputApplicationHandle.get());
+
+ return handle->getInputApplicationHandleObjLocalRef(env);
+}
+
+
nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
const sp<IBinder>& token, const std::string& reason) {
#if DEBUG_INPUT_DISPATCHER_POLICY
@@ -719,12 +731,15 @@
JNIEnv* env = jniEnv();
ScopedLocalFrame localFrame(env);
+ jobject inputApplicationHandleObj =
+ getInputApplicationHandleObjLocalRef(env, inputApplicationHandle);
+
jobject tokenObj = javaObjectForIBinder(env, token);
jstring reasonObj = env->NewStringUTF(reason.c_str());
jlong newTimeout = env->CallLongMethod(mServiceObj,
- gServiceClassInfo.notifyANR, tokenObj,
- reasonObj);
+ gServiceClassInfo.notifyANR, inputApplicationHandleObj, tokenObj,
+ reasonObj);
if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
newTimeout = 0; // abort dispatch
} else {
@@ -1581,8 +1596,8 @@
return JNI_FALSE;
}
- if (im->getInputManager()->getDispatcher()->
- transferTouchFocus(fromChannel->getToken(), toChannel->getToken())) {
+ if (im->getInputManager()->getDispatcher()->transferTouchFocus(
+ fromChannel->getConnectionToken(), toChannel->getConnectionToken())) {
return JNI_TRUE;
} else {
return JNI_FALSE;
@@ -1865,7 +1880,7 @@
GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz,
"notifyANR",
- "(Landroid/os/IBinder;Ljava/lang/String;)J");
+ "(Landroid/view/InputApplicationHandle;Landroid/os/IBinder;Ljava/lang/String;)J");
GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz,
"filterInputEvent", "(Landroid/view/InputEvent;I)Z");
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 5e49c7a..a39cc20 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -8105,15 +8105,7 @@
mSecurityLogMonitor.stop();
setNetworkLoggingActiveInternal(false);
deleteTransferOwnershipBundleLocked(userId);
-
- try {
- if (mInjector.getIBackupManager() != null) {
- // Reactivate backup service.
- mInjector.getIBackupManager().setBackupServiceActive(UserHandle.USER_SYSTEM, true);
- }
- } catch (RemoteException e) {
- throw new IllegalStateException("Failed reactivating backup service.", e);
- }
+ toggleBackupServiceActive(UserHandle.USER_SYSTEM, true);
}
@Override
@@ -8173,7 +8165,6 @@
}
}
-
private void toggleBackupServiceActive(int userId, boolean makeActive) {
long ident = mInjector.binderClearCallingIdentity();
try {
@@ -8182,7 +8173,8 @@
.setBackupServiceActive(userId, makeActive);
}
} catch (RemoteException e) {
- throw new IllegalStateException("Failed deactivating backup service.", e);
+ throw new IllegalStateException(String.format("Failed %s backup service.",
+ makeActive ? "activating" : "deactivating"), e);
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
@@ -8233,6 +8225,7 @@
mOwners.removeProfileOwner(userId);
mOwners.writeProfileOwner(userId);
deleteTransferOwnershipBundleLocked(userId);
+ toggleBackupServiceActive(userId, true);
}
@Override
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 5883048..ef9e69d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -27,6 +27,7 @@
import android.annotation.NonNull;
import android.annotation.StringRes;
import android.app.ActivityThread;
+import android.app.AppCompatCallbacks;
import android.app.INotificationManager;
import android.app.usage.UsageStatsManagerInternal;
import android.content.ComponentName;
@@ -438,7 +439,7 @@
// In case the runtime switched since last boot (such as when
// the old runtime was removed in an OTA), set the system
- // property so that it is in sync. We can | xq oqi't do this in
+ // property so that it is in sync. We can't do this in
// libnativehelper's JniInvocation::Init code where we already
// had to fallback to a different runtime because it is
// running as root and we need to be the system user to set
@@ -646,6 +647,7 @@
ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE, platformCompat);
ServiceManager.addService(Context.PLATFORM_COMPAT_NATIVE_SERVICE,
new PlatformCompatNative(platformCompat));
+ AppCompatCallbacks.install(new long[0]);
t.traceEnd();
// Wait for installd to finish starting up so that it has a chance to
@@ -1133,7 +1135,6 @@
StatusBarManagerService statusBar = null;
INotificationManager notification = null;
- LocationManagerService location = null;
CountryDetectorService countryDetector = null;
ILockSettings lockSettings = null;
MediaRouterService mediaRouter = null;
@@ -1430,12 +1431,7 @@
t.traceEnd();
t.traceBegin("StartLocationManagerService");
- try {
- location = new LocationManagerService(context);
- ServiceManager.addService(Context.LOCATION_SERVICE, location);
- } catch (Throwable e) {
- reportWtf("starting Location Manager", e);
- }
+ mSystemServiceManager.startService(LocationManagerService.Lifecycle.class);
t.traceEnd();
t.traceBegin("StartCountryDetectorService");
@@ -2019,7 +2015,6 @@
final NetworkStatsService networkStatsF = networkStats;
final NetworkPolicyManagerService networkPolicyF = networkPolicy;
final ConnectivityService connectivityF = connectivity;
- final LocationManagerService locationF = location;
final CountryDetectorService countryDetectorF = countryDetector;
final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater;
final InputManagerService inputManagerF = inputManager;
@@ -2175,16 +2170,6 @@
}
t.traceEnd();
-
- t.traceBegin("MakeLocationServiceReady");
- try {
- if (locationF != null) {
- locationF.systemRunning();
- }
- } catch (Throwable e) {
- reportWtf("Notifying Location Service running", e);
- }
- t.traceEnd();
t.traceBegin("MakeCountryDetectionServiceReady");
try {
if (countryDetectorF != null) {
diff --git a/services/net/Android.bp b/services/net/Android.bp
index 2ab8189..c56ecd6 100644
--- a/services/net/Android.bp
+++ b/services/net/Android.bp
@@ -1,7 +1,7 @@
java_library_static {
name: "services.net",
srcs: [
- ":tethering-services-srcs",
+ ":tethering-servicesnet-srcs",
"java/**/*.java",
],
static_libs: [
@@ -29,6 +29,7 @@
"java/android/net/ConnectivityModuleConnector.java",
"java/android/net/NetworkStackClient.java",
"java/android/net/ip/InterfaceController.java",
+ "java/android/net/netlink/*.java",
"java/android/net/util/InterfaceParams.java",
"java/android/net/util/NetdService.java",
"java/android/net/util/NetworkConstants.java",
diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
index 9e7b805..556f96a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
@@ -24,6 +24,7 @@
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doCallRealMethod;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
@@ -35,10 +36,10 @@
import static com.android.server.AlarmManagerService.ACTIVE_INDEX;
import static com.android.server.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED;
import static com.android.server.AlarmManagerService.AlarmHandler.CHARGING_STATUS_CHANGED;
+import static com.android.server.AlarmManagerService.AlarmHandler.REMOVE_FOR_CANCELED;
import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_LONG_TIME;
import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_SHORT_TIME;
import static com.android.server.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
-import static com.android.server.AlarmManagerService.Constants.KEY_APP_STANDBY_QUOTAS_ENABLED;
import static com.android.server.AlarmManagerService.Constants.KEY_LISTENER_TIMEOUT;
import static com.android.server.AlarmManagerService.Constants.KEY_MAX_INTERVAL;
import static com.android.server.AlarmManagerService.Constants.KEY_MIN_FUTURITY;
@@ -81,9 +82,9 @@
import android.util.Log;
import android.util.SparseArray;
-import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.dx.mockito.inline.extended.MockedVoidMethod;
import com.android.internal.annotations.GuardedBy;
import com.android.server.usage.AppStandbyInternal;
@@ -172,7 +173,6 @@
}
public class Injector extends AlarmManagerService.Injector {
- boolean mIsAutomotiveOverride;
Injector(Context context) {
super(context);
@@ -258,12 +258,13 @@
.startMocking();
doReturn(mIActivityManager).when(ActivityManager::getService);
doReturn(mAppStateTracker).when(() -> LocalServices.getService(AppStateTracker.class));
- doReturn(null)
- .when(() -> LocalServices.getService(DeviceIdleInternal.class));
doReturn(mAppStandbyInternal).when(
() -> LocalServices.getService(AppStandbyInternal.class));
doReturn(mUsageStatsManagerInternal).when(
() -> LocalServices.getService(UsageStatsManagerInternal.class));
+ doCallRealMethod().when((MockedVoidMethod) () ->
+ LocalServices.addService(eq(AlarmManagerInternal.class), any()));
+ doCallRealMethod().when(() -> LocalServices.getService(AlarmManagerInternal.class));
when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong()))
.thenReturn(STANDBY_BUCKET_ACTIVE);
@@ -305,6 +306,8 @@
argThat((filter) -> filter.hasAction(BatteryManager.ACTION_CHARGING)
&& filter.hasAction(BatteryManager.ACTION_DISCHARGING)));
mChargingReceiver = chargingReceiverCaptor.getValue();
+
+ setTestableQuotas();
}
private void setTestAlarm(int type, long triggerTime, PendingIntent operation) {
@@ -342,9 +345,10 @@
}
/**
+ * Lowers quotas to make testing feasible.
* Careful while calling as this will replace any existing settings for the calling test.
*/
- private void setQuotasEnabled(boolean enabled) {
+ private void setTestableQuotas() {
final StringBuilder constantsBuilder = new StringBuilder();
constantsBuilder.append(KEY_MIN_FUTURITY);
constantsBuilder.append("=0,");
@@ -353,14 +357,9 @@
constantsBuilder.append("=8,");
constantsBuilder.append(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[WORKING_INDEX]);
constantsBuilder.append("=5,");
- if (!enabled) {
- constantsBuilder.append(KEY_APP_STANDBY_QUOTAS_ENABLED);
- constantsBuilder.append("=false,");
- }
doReturn(constantsBuilder.toString()).when(() -> Settings.Global.getString(mMockResolver,
Settings.Global.ALARM_MANAGER_CONSTANTS));
mService.mConstants.onChange(false, null);
- assertEquals(mService.mConstants.APP_STANDBY_QUOTAS_ENABLED, enabled);
}
@Test
@@ -458,7 +457,6 @@
assertEquals(expectedTriggerTime, mTestTimer.getElapsed());
}
- @FlakyTest(bugId = 130313408)
@Test
public void testEarliestAlarmSet() {
final PendingIntent pi6 = getNewMockPendingIntent();
@@ -481,67 +479,6 @@
assertEquals(mNowElapsedTest + 9, mTestTimer.getElapsed());
}
- @Test
- public void testStandbyBucketDelay_workingSet() throws Exception {
- setQuotasEnabled(false);
- setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent());
- setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent());
- assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed());
-
- when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
- anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET);
-
- mNowElapsedTest = mTestTimer.getElapsed();
- mTestTimer.expire();
-
- verify(mUsageStatsManagerInternal, atLeastOnce())
- .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
- eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong());
- final long expectedNextTrigger = mNowElapsedTest
- + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_WORKING_SET);
- assertEquals("Incorrect next alarm trigger", expectedNextTrigger, mTestTimer.getElapsed());
- }
-
- @Test
- public void testStandbyBucketDelay_frequent() throws Exception {
- setQuotasEnabled(false);
- setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent());
- setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent());
- assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed());
-
- when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
- anyLong())).thenReturn(STANDBY_BUCKET_FREQUENT);
- mNowElapsedTest = mTestTimer.getElapsed();
- mTestTimer.expire();
-
- verify(mUsageStatsManagerInternal, atLeastOnce())
- .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
- eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong());
- final long expectedNextTrigger = mNowElapsedTest
- + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_FREQUENT);
- assertEquals("Incorrect next alarm trigger.", expectedNextTrigger, mTestTimer.getElapsed());
- }
-
- @Test
- public void testStandbyBucketDelay_rare() throws Exception {
- setQuotasEnabled(false);
- setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 5, getNewMockPendingIntent());
- setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 6, getNewMockPendingIntent());
- assertEquals(mNowElapsedTest + 5, mTestTimer.getElapsed());
-
- when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
- anyLong())).thenReturn(STANDBY_BUCKET_RARE);
- mNowElapsedTest = mTestTimer.getElapsed();
- mTestTimer.expire();
-
- verify(mUsageStatsManagerInternal, atLeastOnce())
- .getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
- eq(UserHandle.getUserId(TEST_CALLING_UID)), anyLong());
- final long expectedNextTrigger = mNowElapsedTest
- + mService.getMinDelayForBucketLocked(STANDBY_BUCKET_RARE);
- assertEquals("Incorrect next alarm trigger.", expectedNextTrigger, mTestTimer.getElapsed());
- }
-
private void testQuotasDeferralOnSet(int standbyBucket) throws Exception {
final int quota = mService.getQuotaForBucketLocked(standbyBucket);
when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
@@ -601,73 +538,61 @@
@Test
public void testActiveQuota_deferredOnSet() throws Exception {
- setQuotasEnabled(true);
testQuotasDeferralOnSet(STANDBY_BUCKET_ACTIVE);
}
@Test
public void testActiveQuota_deferredOnExpiration() throws Exception {
- setQuotasEnabled(true);
testQuotasDeferralOnExpiration(STANDBY_BUCKET_ACTIVE);
}
@Test
public void testActiveQuota_notDeferred() throws Exception {
- setQuotasEnabled(true);
testQuotasNoDeferral(STANDBY_BUCKET_ACTIVE);
}
@Test
public void testWorkingQuota_deferredOnSet() throws Exception {
- setQuotasEnabled(true);
testQuotasDeferralOnSet(STANDBY_BUCKET_WORKING_SET);
}
@Test
public void testWorkingQuota_deferredOnExpiration() throws Exception {
- setQuotasEnabled(true);
testQuotasDeferralOnExpiration(STANDBY_BUCKET_WORKING_SET);
}
@Test
public void testWorkingQuota_notDeferred() throws Exception {
- setQuotasEnabled(true);
testQuotasNoDeferral(STANDBY_BUCKET_WORKING_SET);
}
@Test
public void testFrequentQuota_deferredOnSet() throws Exception {
- setQuotasEnabled(true);
testQuotasDeferralOnSet(STANDBY_BUCKET_FREQUENT);
}
@Test
public void testFrequentQuota_deferredOnExpiration() throws Exception {
- setQuotasEnabled(true);
testQuotasDeferralOnExpiration(STANDBY_BUCKET_FREQUENT);
}
@Test
public void testFrequentQuota_notDeferred() throws Exception {
- setQuotasEnabled(true);
testQuotasNoDeferral(STANDBY_BUCKET_FREQUENT);
}
@Test
public void testRareQuota_deferredOnSet() throws Exception {
- setQuotasEnabled(true);
testQuotasDeferralOnSet(STANDBY_BUCKET_RARE);
}
@Test
public void testRareQuota_deferredOnExpiration() throws Exception {
- setQuotasEnabled(true);
testQuotasDeferralOnExpiration(STANDBY_BUCKET_RARE);
}
@Test
public void testRareQuota_notDeferred() throws Exception {
- setQuotasEnabled(true);
testQuotasNoDeferral(STANDBY_BUCKET_RARE);
}
@@ -676,17 +601,20 @@
anyLong())).thenReturn(bucket);
mAppStandbyListener.onAppIdleStateChanged(TEST_CALLING_PACKAGE,
UserHandle.getUserId(TEST_CALLING_UID), false, bucket, 0);
+ assertAndHandleMessageSync(APP_STANDBY_BUCKET_CHANGED);
+ }
+
+ private void assertAndHandleMessageSync(int what) {
final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
verify(mService.mHandler, atLeastOnce()).sendMessage(messageCaptor.capture());
final Message lastMessage = messageCaptor.getValue();
assertEquals("Unexpected message send to handler", lastMessage.what,
- APP_STANDBY_BUCKET_CHANGED);
+ what);
mService.mHandler.handleMessage(lastMessage);
}
@Test
public void testQuotaDowngrade() throws Exception {
- setQuotasEnabled(true);
final int workingQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_WORKING_SET);
when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET);
@@ -714,7 +642,6 @@
@Test
public void testQuotaUpgrade() throws Exception {
- setQuotasEnabled(true);
final int frequentQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_FREQUENT);
when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
anyLong())).thenReturn(STANDBY_BUCKET_FREQUENT);
@@ -742,17 +669,11 @@
mChargingReceiver.onReceive(mMockContext,
new Intent(parole ? BatteryManager.ACTION_CHARGING
: BatteryManager.ACTION_DISCHARGING));
- final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
- verify(mService.mHandler, atLeastOnce()).sendMessage(messageCaptor.capture());
- final Message lastMessage = messageCaptor.getValue();
- assertEquals("Unexpected message send to handler", lastMessage.what,
- CHARGING_STATUS_CHANGED);
- mService.mHandler.handleMessage(lastMessage);
+ assertAndHandleMessageSync(CHARGING_STATUS_CHANGED);
}
@Test
public void testCharging() throws Exception {
- setQuotasEnabled(true);
final int workingQuota = mService.getQuotaForBucketLocked(STANDBY_BUCKET_WORKING_SET);
when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE), anyInt(),
anyLong())).thenReturn(STANDBY_BUCKET_WORKING_SET);
@@ -1050,12 +971,13 @@
}
@Test
- public void alarmCountOnPendingIntentCancel() {
+ public void alarmCountOnRemoveForCanceled() {
+ final AlarmManagerInternal ami = LocalServices.getService(AlarmManagerInternal.class);
final PendingIntent pi = getNewMockPendingIntent();
- setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 123, pi);
- verify(pi).registerCancelListener(mService.mOperationCancelListener);
+ setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + 12345, pi);
assertEquals(1, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
- mService.mOperationCancelListener.onCancelled(pi);
+ ami.remove(pi);
+ assertAndHandleMessageSync(REMOVE_FOR_CANCELED);
assertEquals(0, mService.mAlarmsPerUid.get(TEST_CALLING_UID));
}
@@ -1064,5 +986,6 @@
if (mMockingSession != null) {
mMockingSession.finishMocking();
}
+ LocalServices.removeServiceForTest(AlarmManagerInternal.class);
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
index 1f4656a..1e27007 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
@@ -513,7 +513,8 @@
mIUidObserver.onUidStateChanged(UID_2,
- ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE, 0);
+ ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
waitUntilMainHandlerDrain();
assertTrue(instance.isUidActive(UID_1));
@@ -530,7 +531,8 @@
mIUidObserver.onUidStateChanged(UID_1,
- ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
+ ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
waitUntilMainHandlerDrain();
assertTrue(instance.isUidActive(UID_1));
@@ -564,7 +566,8 @@
assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
mIUidObserver.onUidStateChanged(UID_1,
- ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0);
+ ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
waitUntilMainHandlerDrain();
assertFalse(instance.isUidActive(UID_1));
@@ -576,7 +579,8 @@
assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
mIUidObserver.onUidStateChanged(UID_1,
- ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0);
+ ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
waitUntilMainHandlerDrain();
assertFalse(instance.isUidActive(UID_1));
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 6dd1bd8..e7f6a74 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -23,7 +23,6 @@
import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY;
import static android.app.ActivityManager.PROCESS_STATE_CACHED_RECENT;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
-import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION;
import static android.app.ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
import static android.app.ActivityManager.PROCESS_STATE_HOME;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
@@ -62,6 +61,7 @@
import static com.android.server.am.ProcessList.VISIBLE_APP_ADJ;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.mockito.AdditionalAnswers.answer;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
@@ -368,7 +368,7 @@
sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
sService.mOomAdjuster.updateOomAdjLocked(app, false, OomAdjuster.OOM_ADJ_REASON_NONE);
- assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE_LOCATION, PERCEPTIBLE_APP_ADJ,
+ assertProcStates(app, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
SCHED_GROUP_DEFAULT);
}
@@ -543,6 +543,21 @@
@SuppressWarnings("GuardedBy")
@Test
+ public void testUpdateOomAdj_DoOne_NonCachedToCached() {
+ ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ app.cached = false;
+ app.setCurRawAdj(SERVICE_ADJ);
+ doReturn(null).when(sService).getTopAppLocked();
+ sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+ sService.mOomAdjuster.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertTrue(ProcessList.CACHED_APP_MIN_ADJ <= app.setAdj);
+ assertTrue(ProcessList.CACHED_APP_MAX_ADJ >= app.setAdj);
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
public void testUpdateOomAdj_DoOne_Service_Started() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
new file mode 100644
index 0000000..3975f0b
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/am/PendingIntentControllerTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
+import android.app.AppGlobals;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.content.pm.IPackageManager;
+import android.os.Looper;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.AlarmManagerInternal;
+import com.android.server.LocalServices;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+@RunWith(AndroidJUnit4.class)
+public class PendingIntentControllerTest {
+ private static final String TEST_PACKAGE_NAME = "test-package-1";
+ private static final int TEST_CALLING_UID = android.os.Process.myUid();
+ private static final Intent[] TEST_INTENTS = new Intent[]{new Intent("com.test.intent")};
+
+ @Mock
+ private UserController mUserController;
+ @Mock
+ private AlarmManagerInternal mAlarmManagerInternal;
+ @Mock
+ private ActivityManagerInternal mActivityManagerInternal;
+ @Mock
+ private IPackageManager mIPackageManager;
+
+ private MockitoSession mMockingSession;
+ private PendingIntentController mPendingIntentController;
+
+ @Before
+ public void setUp() throws Exception {
+ mMockingSession = mockitoSession()
+ .initMocks(this)
+ .mockStatic(LocalServices.class)
+ .mockStatic(AppGlobals.class)
+ .strictness(Strictness.LENIENT) // Needed to stub LocalServices.getService twice
+ .startMocking();
+ doReturn(mAlarmManagerInternal).when(
+ () -> LocalServices.getService(AlarmManagerInternal.class));
+ doReturn(mActivityManagerInternal).when(
+ () -> LocalServices.getService(ActivityManagerInternal.class));
+ doReturn(mIPackageManager).when(() -> AppGlobals.getPackageManager());
+ when(mIPackageManager.getPackageUid(eq(TEST_PACKAGE_NAME), anyInt(), anyInt())).thenReturn(
+ TEST_CALLING_UID);
+ mPendingIntentController = new PendingIntentController(Looper.getMainLooper(),
+ mUserController);
+ mPendingIntentController.onActivityManagerInternalAdded();
+ }
+
+ private PendingIntentRecord createPendingIntentRecord(int flags) {
+ return mPendingIntentController.getIntentSender(ActivityManager.INTENT_SENDER_BROADCAST,
+ TEST_PACKAGE_NAME, TEST_CALLING_UID, 0, null, null, 0, TEST_INTENTS, null, flags,
+ null);
+ }
+
+ @Test
+ public void alarmsRemovedOnCancel() {
+ final PendingIntentRecord pir = createPendingIntentRecord(0);
+ mPendingIntentController.cancelIntentSender(pir);
+ final ArgumentCaptor<PendingIntent> piCaptor = ArgumentCaptor.forClass(PendingIntent.class);
+ verify(mAlarmManagerInternal).remove(piCaptor.capture());
+ assertEquals("Wrong target for pending intent passed to alarm manager", pir,
+ piCaptor.getValue().getTarget());
+ }
+
+ @Test
+ public void alarmsRemovedOnRecreateWithCancelCurrent() {
+ final PendingIntentRecord pir = createPendingIntentRecord(0);
+ createPendingIntentRecord(PendingIntent.FLAG_CANCEL_CURRENT);
+ final ArgumentCaptor<PendingIntent> piCaptor = ArgumentCaptor.forClass(PendingIntent.class);
+ verify(mAlarmManagerInternal).remove(piCaptor.capture());
+ assertEquals("Wrong target for pending intent passed to alarm manager", pir,
+ piCaptor.getValue().getTarget());
+ }
+
+ @Test
+ public void alarmsRemovedOnSendingOneShot() {
+ final PendingIntentRecord pir = createPendingIntentRecord(PendingIntent.FLAG_ONE_SHOT);
+ pir.send(0, null, null, null, null, null, null);
+ final ArgumentCaptor<PendingIntent> piCaptor = ArgumentCaptor.forClass(PendingIntent.class);
+ verify(mAlarmManagerInternal).remove(piCaptor.capture());
+ assertEquals("Wrong target for pending intent passed to alarm manager", pir,
+ piCaptor.getValue().getTarget());
+ }
+
+ @After
+ public void tearDown() {
+ if (mMockingSession != null) {
+ mMockingSession.finishMocking();
+ }
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index b6a7b09..fa209a7a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -16,7 +16,6 @@
package com.android.server.appop;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
-import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.MODE_FOREGROUND;
@@ -338,18 +337,22 @@
public void testUidProcStateChange_cachedToTopToCached() throws Exception {
setupProcStateTests();
- mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+ mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
.isNotEqualTo(MODE_ALLOWED);
- mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP);
+ mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
+ ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
.isEqualTo(MODE_ALLOWED);
- mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+ mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
// Second time to make sure that settle time is overcome
Thread.sleep(50);
- mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+ mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
.isNotEqualTo(MODE_ALLOWED);
}
@@ -357,12 +360,13 @@
@Test
public void testUidProcStateChange_cachedToFgs() {
setupProcStateTests();
-
- mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+ mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
.isNotEqualTo(MODE_ALLOWED);
- mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
+ mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
.isNotEqualTo(MODE_ALLOWED);
}
@@ -371,12 +375,13 @@
public void testUidProcStateChange_cachedToFgsLocation() {
setupProcStateTests();
- mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+ mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
.isNotEqualTo(MODE_ALLOWED);
- mAppOpsService.updateUidProcState(mMyUid,
- PROCESS_STATE_FOREGROUND_SERVICE_LOCATION);
+ mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
+ ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
.isEqualTo(MODE_ALLOWED);
}
@@ -385,18 +390,22 @@
public void testUidProcStateChange_topToFgs() throws Exception {
setupProcStateTests();
- mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+ mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
.isNotEqualTo(MODE_ALLOWED);
- mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP);
+ mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
+ ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
.isEqualTo(MODE_ALLOWED);
- mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
+ mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
// Second time to make sure that settle time is overcome
Thread.sleep(50);
- mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
+ mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
.isNotEqualTo(MODE_ALLOWED);
}
@@ -405,25 +414,31 @@
public void testUidProcStateChange_topToFgsLocationToFgs() throws Exception {
setupProcStateTests();
- mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
+ mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
.isNotEqualTo(MODE_ALLOWED);
- mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP);
+ mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
+ ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
.isEqualTo(MODE_ALLOWED);
- mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE_LOCATION);
+ mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
+ ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
// Second time to make sure that settle time is overcome
Thread.sleep(50);
- mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE_LOCATION);
+ mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
+ ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
.isEqualTo(MODE_ALLOWED);
- mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
+ mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
// Second time to make sure that settle time is overcome
Thread.sleep(50);
- mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE);
+ mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null))
.isNotEqualTo(MODE_ALLOWED);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index 8863d5a..5bd08c0 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -233,7 +233,8 @@
doReturn(procState).when(mActivityMangerInternal).getUidProcessState(uid);
SparseBooleanArray foregroundUids = mQuotaController.getForegroundUids();
spyOn(foregroundUids);
- mUidObserver.onUidStateChanged(uid, procState, 0);
+ mUidObserver.onUidStateChanged(uid, procState, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
verify(foregroundUids, timeout(2 * SECOND_IN_MILLIS).times(1))
.put(eq(uid), eq(true));
diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml
index 4d653b9..d34f783 100644
--- a/services/tests/servicestests/AndroidTest.xml
+++ b/services/tests/servicestests/AndroidTest.xml
@@ -23,6 +23,7 @@
<option name="test-file-name" value="JobTestApp.apk" />
<option name="test-file-name" value="ConnTestApp.apk" />
<option name="test-file-name" value="SuspendTestApp.apk" />
+ <option name="test-file-name" value="SimpleServiceTestApp.apk" />
</target_preparer>
<option name="test-tag" value="FrameworksServicesTests" />
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 1ad7b6e..79af34d 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -191,7 +191,7 @@
@After
public void tearDown() throws Exception {
mHandlerThread.quitSafely();
- LocalServices.removeServiceForTest(PackageManagerInternal.class);
+ LocalServices.removeServiceForTest(PermissionManagerServiceInternal.class);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
index 1edc953..49412bc0c 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerServiceTest.java
@@ -571,7 +571,8 @@
verifyObserverReceivedChanges(observerToTest, changesToVerify, changeItems,
(observer, changeItem) -> {
verify(observer).onUidStateChanged(changeItem.uid,
- changeItem.processState, changeItem.procStateSeq);
+ changeItem.processState, changeItem.procStateSeq,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
});
}
// Verify there are no other callbacks for this observer.
@@ -619,7 +620,8 @@
// First process state message is always delivered regardless of whether the process state
// change is above or below the cutpoint (PROCESS_STATE_SERVICE).
verify(observer).onUidStateChanged(TEST_UID,
- changeItem.processState, changeItem.procStateSeq);
+ changeItem.processState, changeItem.procStateSeq,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
verifyNoMoreInteractions(observer);
changeItem.processState = ActivityManager.PROCESS_STATE_RECEIVER;
@@ -636,7 +638,8 @@
// the current process state change is above cutpoint, so callback will be invoked with the
// current process state change.
verify(observer).onUidStateChanged(TEST_UID,
- changeItem.processState, changeItem.procStateSeq);
+ changeItem.processState, changeItem.procStateSeq,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
verifyNoMoreInteractions(observer);
changeItem.processState = ActivityManager.PROCESS_STATE_TOP;
@@ -653,7 +656,8 @@
// the current process state change is below cutpoint, so callback will be invoked with the
// current process state change.
verify(observer).onUidStateChanged(TEST_UID,
- changeItem.processState, changeItem.procStateSeq);
+ changeItem.processState, changeItem.procStateSeq,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
verifyNoMoreInteractions(observer);
}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java
index 8965152..129d263 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java
@@ -19,20 +19,34 @@
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo;
import android.app.IActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.os.IBinder;
+import android.os.IRemoteCallback;
import android.os.RemoteException;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
+import android.support.test.uiautomator.UiDevice;
+import androidx.test.InstrumentationRegistry;
import androidx.test.filters.FlakyTest;
import org.junit.Before;
import org.junit.Test;
+import java.io.IOException;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* Tests for {@link ActivityManager}.
@@ -43,12 +57,22 @@
@FlakyTest(detail = "Promote to presubmit if stable")
@Presubmit
public class ActivityManagerTest {
+ private static final String TAG = "ActivityManagerTest";
+
+ private static final String TEST_APP = "com.android.servicestests.apps.simpleservicetestapp";
+ private static final String TEST_CLASS = TEST_APP + ".SimpleService";
+ private static final int TEST_LOOPS = 100;
+ private static final long AWAIT_TIMEOUT = 2000;
+ private static final long CHECK_INTERVAL = 100;
private IActivityManager mService;
+ private IRemoteCallback mCallback;
+ private Context mContext;
@Before
public void setUp() throws Exception {
mService = ActivityManager.getService();
+ mContext = InstrumentationRegistry.getTargetContext();
}
@Test
@@ -72,4 +96,112 @@
}
}
}
+
+ @Test
+ public void testServiceUnbindAndKilling() {
+ for (int i = TEST_LOOPS; i > 0; i--) {
+ runOnce(i);
+ }
+ }
+
+ private void runOnce(long yieldDuration) {
+ final PackageManager pm = mContext.getPackageManager();
+ int uid = 0;
+ try {
+ uid = pm.getPackageUid(TEST_APP, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+
+ Intent intent = new Intent();
+ intent.setClassName(TEST_APP, TEST_CLASS);
+
+ // Create a service connection with auto creation.
+ CountDownLatch latch = new CountDownLatch(1);
+ final MyServiceConnection autoConnection = new MyServiceConnection(latch);
+ mContext.bindService(intent, autoConnection, Context.BIND_AUTO_CREATE);
+ try {
+ assertTrue("Timeout to bind to service " + intent.getComponent(),
+ latch.await(AWAIT_TIMEOUT, TimeUnit.MILLISECONDS));
+ } catch (InterruptedException e) {
+ fail("Unable to bind to service " + intent.getComponent());
+ }
+
+ // Create a service connection without any flags.
+ intent = new Intent();
+ intent.setClassName(TEST_APP, TEST_CLASS);
+ latch = new CountDownLatch(1);
+ MyServiceConnection otherConnection = new MyServiceConnection(latch);
+ mContext.bindService(intent, otherConnection, 0);
+ try {
+ assertTrue("Timeout to bind to service " + intent.getComponent(),
+ latch.await(AWAIT_TIMEOUT, TimeUnit.MILLISECONDS));
+ } catch (InterruptedException e) {
+ fail("Unable to bind to service " + intent.getComponent());
+ }
+
+ // Inform the remote process to kill itself
+ try {
+ mCallback.sendResult(null);
+ // It's basically a test for race condition, we expect the bringDownServiceLocked()
+ // would find out the hosting process is dead - to do this, technically we should
+ // do killing and unbinding simultaneously; but in reality, the killing would take
+ // a little while, before the signal really kills it; so we do it in the same thread,
+ // and even wait a while after sending killing signal.
+ Thread.sleep(yieldDuration);
+ } catch (RemoteException | InterruptedException e) {
+ fail("Unable to kill the process");
+ }
+ // Now unbind that auto connection, this should be equivalent to stopService
+ mContext.unbindService(autoConnection);
+
+ // Now we don't expect the system_server crashes.
+
+ // Wait for the target process dies
+ long total = 0;
+ for (; total < AWAIT_TIMEOUT; total += CHECK_INTERVAL) {
+ try {
+ if (!targetPackageIsRunning(mContext, uid)) {
+ break;
+ }
+ Thread.sleep(CHECK_INTERVAL);
+ } catch (InterruptedException e) {
+ }
+ }
+ assertTrue("Timeout to wait for the target package dies", total < AWAIT_TIMEOUT);
+ mCallback = null;
+ }
+
+ private boolean targetPackageIsRunning(Context context, int uid) {
+ final String result = runShellCommand(
+ String.format("cmd activity get-uid-state %d", uid));
+ return !result.contains("(NONEXISTENT)");
+ }
+
+ private static String runShellCommand(String cmd) {
+ try {
+ return UiDevice.getInstance(
+ InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private class MyServiceConnection implements ServiceConnection {
+ private CountDownLatch mLatch;
+
+ MyServiceConnection(CountDownLatch latch) {
+ this.mLatch = latch;
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mCallback = IRemoteCallback.Stub.asInterface(service);
+ mLatch.countDown();
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ }
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java b/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java
index d3bcff5..d12d804 100644
--- a/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/OomAdjusterTests.java
@@ -181,7 +181,7 @@
@Test
public void testMaybeUpdateUsageStats_ProcStateFGSLocation() {
final long elapsedTime = ZERO;
- mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE_LOCATION);
+ mProcessRecord.setCurProcState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
sService.mOomAdjuster.maybeUpdateUsageStats(mProcessRecord, elapsedTime);
assertProcessRecordState(elapsedTime, false, ZERO);
diff --git a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
index 184dc3d..a47a567 100644
--- a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
@@ -16,6 +16,8 @@
package com.android.server.attention;
+import static com.android.server.attention.AttentionManagerService.ATTENTION_CACHE_BUFFER_SIZE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -39,6 +41,8 @@
import androidx.test.filters.SmallTest;
import com.android.server.attention.AttentionManagerService.AttentionCheck;
+import com.android.server.attention.AttentionManagerService.AttentionCheckCache;
+import com.android.server.attention.AttentionManagerService.AttentionCheckCacheBuffer;
import com.android.server.attention.AttentionManagerService.AttentionHandler;
import com.android.server.attention.AttentionManagerService.UserState;
@@ -56,11 +60,16 @@
private AttentionManagerService mSpyAttentionManager;
private UserState mSpyUserState;
private final int mTimeout = 1000;
- @Mock private AttentionCallbackInternal mMockAttentionCallbackInternal;
- @Mock private AttentionHandler mMockHandler;
- @Mock private IAttentionCallback mMockIAttentionCallback;
- @Mock private IPowerManager mMockIPowerManager;
- @Mock Context mContext;
+ @Mock
+ private AttentionCallbackInternal mMockAttentionCallbackInternal;
+ @Mock
+ private AttentionHandler mMockHandler;
+ @Mock
+ private IAttentionCallback mMockIAttentionCallback;
+ @Mock
+ private IPowerManager mMockIPowerManager;
+ @Mock
+ Context mContext;
@Before
public void setUp() throws RemoteException {
@@ -140,12 +149,45 @@
mSpyAttentionManager.onSwitchUser(userId);
}
+ @Test
+ public void testAttentionCheckCacheBuffer_getLast_returnTheLastElement() {
+ AttentionCheckCacheBuffer buffer = new AttentionCheckCacheBuffer();
+ buffer.add(new AttentionCheckCache(0, 0, 1L));
+ AttentionCheckCache cache = new AttentionCheckCache(0, 0, 2L);
+ buffer.add(cache);
+ assertThat(buffer.getLast()).isEqualTo(cache);
+ }
+
+ @Test
+ public void testAttentionCheckCacheBuffer_get_returnNullWhenOutOfBoundary() {
+ AttentionCheckCacheBuffer buffer = new AttentionCheckCacheBuffer();
+ assertThat(buffer.get(1)).isNull();
+ }
+
+ @Test
+ public void testAttentionCheckCacheBuffer_get_handleCircularIndexing() {
+ AttentionCheckCacheBuffer buffer = new AttentionCheckCacheBuffer();
+ AttentionCheckCache cache = new AttentionCheckCache(0L, 0, 1L);
+ // Insert SIZE+1 elements.
+ for (int i = 0; i <= ATTENTION_CACHE_BUFFER_SIZE; i++) {
+ if (i == 1) {
+ buffer.add(cache);
+ } else {
+ buffer.add(new AttentionCheckCache(0L, 0, i));
+ }
+ }
+ // The element that was at index 1 should be at index 0 after inserting SIZE + 1 elements.
+ assertThat(buffer.get(0)).isEqualTo(cache);
+ }
+
private class MockIAttentionService implements IAttentionService {
public void checkAttention(IAttentionCallback callback) throws RemoteException {
callback.onSuccess(0, 0);
}
+
public void cancelAttentionCheck(IAttentionCallback callback) {
}
+
public IBinder asBinder() {
return null;
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index aeccfc5..f571411 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -943,10 +943,6 @@
verify(getServices().iactivityManager, times(1)).updateDeviceOwner(
eq(admin1.getPackageName()));
- // TODO We should check if the caller has called clearCallerIdentity().
- verify(getServices().ibackupManager, times(1)).setBackupServiceActive(
- eq(UserHandle.USER_SYSTEM), eq(false));
-
verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
MockUtils.checkIntentAction(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED),
MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
@@ -1175,6 +1171,37 @@
// TODO Check other calls.
}
+ public void testDeviceOwnerBackupActivateDeactivate() throws Exception {
+ mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
+ mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
+
+ // Set admin1 as a DA to the secondary user.
+ mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+ setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
+ dpm.setActiveAdmin(admin1, /* replace =*/ false);
+ assertTrue(dpm.setDeviceOwner(admin1, "owner-name"));
+
+ verify(getServices().ibackupManager, times(1)).setBackupServiceActive(
+ eq(UserHandle.USER_SYSTEM), eq(false));
+
+ dpm.clearDeviceOwnerApp(admin1.getPackageName());
+
+ verify(getServices().ibackupManager, times(1)).setBackupServiceActive(
+ eq(UserHandle.USER_SYSTEM), eq(true));
+ }
+
+ public void testProfileOwnerBackupActivateDeactivate() throws Exception {
+ setAsProfileOwner(admin1);
+
+ verify(getServices().ibackupManager, times(1)).setBackupServiceActive(
+ eq(DpmMockContext.CALLER_USER_HANDLE), eq(false));
+
+ dpm.clearProfileOwner(admin1);
+
+ verify(getServices().ibackupManager, times(1)).setBackupServiceActive(
+ eq(DpmMockContext.CALLER_USER_HANDLE), eq(true));
+ }
+
public void testClearDeviceOwner_fromDifferentUser() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_USERS);
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 64bd2c7..51bae16 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -1362,7 +1362,8 @@
private void callOnUidStateChanged(int uid, int procState, long procStateSeq)
throws Exception {
- mUidObserver.onUidStateChanged(uid, procState, procStateSeq);
+ mUidObserver.onUidStateChanged(uid, procState, procStateSeq,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
final CountDownLatch latch = new CountDownLatch(1);
mService.mUidEventHandler.post(() -> {
latch.countDown();
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index b806180..f9fc3a1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -2222,7 +2222,8 @@
protected void makeUidForeground(int uid) {
try {
mService.mUidObserver.onUidStateChanged(
- uid, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
+ uid, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
@@ -2235,7 +2236,8 @@
protected void makeUidBackground(int uid) {
try {
mService.mUidObserver.onUidStateChanged(
- uid, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0);
+ uid, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index fd3678d..7b101c7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -1647,7 +1647,8 @@
// State changed, but not foreground, so no resetting.
mService.mUidObserver.onUidStateChanged(
- CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0);
+ CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
@@ -1671,7 +1672,8 @@
// State changed, package1 foreground, reset.
mService.mUidObserver.onUidStateChanged(
- CALLING_UID_1, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
+ CALLING_UID_1, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
});
@@ -1691,16 +1693,19 @@
MoreAsserts.assertNotEqual(3, mManager.getRemainingCallCount());
});
mService.mUidObserver.onUidStateChanged(
- CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0);
+ CALLING_UID_1, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
mInjectedCurrentTimeMillis++;
// Different app comes to foreground briefly, and goes back to background.
// Now, make sure package 2's counter is reset, even in this case.
mService.mUidObserver.onUidStateChanged(
- CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
+ CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
mService.mUidObserver.onUidStateChanged(
- CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0);
+ CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
@@ -1731,9 +1736,11 @@
});
mService.mUidObserver.onUidStateChanged(
- CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
+ CALLING_UID_2, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
mService.mUidObserver.onUidStateChanged(
- CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0);
+ CALLING_UID_2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
@@ -1760,7 +1767,8 @@
// Now, also try calling some APIs and make sure foreground apps don't get throttled.
mService.mUidObserver.onUidStateChanged(
UserHandle.getUid(USER_10, CALLING_UID_1),
- ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0);
+ ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
assertEquals(3, mManager.getRemainingCallCount());
assertFalse(mManager.isRateLimitingActive());
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
index 0196279..f08044c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
@@ -691,35 +691,16 @@
}
}
- private boolean shouldPackageRunOob(
- boolean isDefaultEnabled, String defaultWhitelist, String overrideEnabled,
- String overrideWhitelist, Collection<String> packageNamesInSameProcess) {
+ private boolean shouldPackageRunOob(boolean isDefaultEnabled, String whitelist,
+ Collection<String> packageNamesInSameProcess) {
return DexManager.isPackageSelectedToRunOobInternal(
- isDefaultEnabled, defaultWhitelist, overrideEnabled, overrideWhitelist,
- packageNamesInSameProcess);
+ isDefaultEnabled, whitelist, packageNamesInSameProcess);
}
@Test
- public void testOobPackageSelectionSwitch() {
+ public void testOobPackageSelectionDefault() {
// Feature is off by default, not overriden
- assertFalse(shouldPackageRunOob(false, "ALL", null, null, null));
-
- // Feature is off by default, overriden
- assertTrue(shouldPackageRunOob(false, "ALL", "true", "ALL", null));
- assertFalse(shouldPackageRunOob(false, "ALL", "false", null, null));
- assertFalse(shouldPackageRunOob(false, "ALL", "false", "ALL", null));
- assertFalse(shouldPackageRunOob(false, "ALL", "false", null, null));
-
- // Feature is on by default, not overriden
- assertTrue(shouldPackageRunOob(true, "ALL", null, null, null));
- assertTrue(shouldPackageRunOob(true, "ALL", null, null, null));
- assertTrue(shouldPackageRunOob(true, "ALL", null, "ALL", null));
-
- // Feature is on by default, overriden
- assertTrue(shouldPackageRunOob(true, "ALL", "true", null, null));
- assertTrue(shouldPackageRunOob(true, "ALL", "true", "ALL", null));
- assertFalse(shouldPackageRunOob(true, "ALL", "false", null, null));
- assertFalse(shouldPackageRunOob(true, "ALL", "false", "ALL", null));
+ assertFalse(shouldPackageRunOob(false, "ALL", null));
}
@Test
@@ -734,24 +715,19 @@
final Collection<String> runningPackages = Arrays.asList("com.priv.app1", "com.priv.app2");
// Feature is off, whitelist does not matter
- assertFalse(shouldPackageRunOob(false, kWhitelistApp0, null, null, runningPackages));
- assertFalse(shouldPackageRunOob(false, kWhitelistApp1, null, null, runningPackages));
- assertFalse(shouldPackageRunOob(false, "", null, kWhitelistApp1, runningPackages));
- assertFalse(shouldPackageRunOob(false, "", null, "ALL", runningPackages));
- assertFalse(shouldPackageRunOob(false, "ALL", null, "ALL", runningPackages));
- assertFalse(shouldPackageRunOob(false, "ALL", null, "", runningPackages));
+ assertFalse(shouldPackageRunOob(false, kWhitelistApp0, runningPackages));
+ assertFalse(shouldPackageRunOob(false, kWhitelistApp1, runningPackages));
+ assertFalse(shouldPackageRunOob(false, "", runningPackages));
+ assertFalse(shouldPackageRunOob(false, "ALL", runningPackages));
- // Feature is on, app not in default or overridden whitelist
- assertFalse(shouldPackageRunOob(true, kWhitelistApp0, null, null, runningPackages));
- assertFalse(shouldPackageRunOob(true, "", null, kWhitelistApp0, runningPackages));
- assertFalse(shouldPackageRunOob(true, "ALL", null, kWhitelistApp0, runningPackages));
+ // Feature is on, app not in whitelist
+ assertFalse(shouldPackageRunOob(true, kWhitelistApp0, runningPackages));
+ assertFalse(shouldPackageRunOob(true, "", runningPackages));
- // Feature is on, app in default or overridden whitelist
- assertTrue(shouldPackageRunOob(true, kWhitelistApp1, null, null, runningPackages));
- assertTrue(shouldPackageRunOob(true, kWhitelistApp2, null, null, runningPackages));
- assertTrue(shouldPackageRunOob(true, kWhitelistApp1AndApp2, null, null, runningPackages));
- assertTrue(shouldPackageRunOob(true, kWhitelistApp1, null, "ALL", runningPackages));
- assertTrue(shouldPackageRunOob(true, "", null, kWhitelistApp1, runningPackages));
- assertTrue(shouldPackageRunOob(true, "ALL", null, kWhitelistApp1, runningPackages));
+ // Feature is on, app in whitelist
+ assertTrue(shouldPackageRunOob(true, kWhitelistApp1, runningPackages));
+ assertTrue(shouldPackageRunOob(true, kWhitelistApp2, runningPackages));
+ assertTrue(shouldPackageRunOob(true, kWhitelistApp1AndApp2, runningPackages));
+ assertTrue(shouldPackageRunOob(true, "ALL", runningPackages));
}
}
diff --git a/services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp b/services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp
new file mode 100644
index 0000000..5cbd39c
--- /dev/null
+++ b/services/tests/servicestests/test-apps/SimpleServiceTestApp/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test_helper_app {
+ name: "SimpleServiceTestApp",
+
+ test_suites: ["device-tests"],
+
+ srcs: ["**/*.java"],
+
+ platform_apis: true,
+ certificate: "platform",
+ dex_preopt: {
+ enabled: false,
+ },
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/services/tests/servicestests/test-apps/SimpleServiceTestApp/AndroidManifest.xml b/services/tests/servicestests/test-apps/SimpleServiceTestApp/AndroidManifest.xml
new file mode 100644
index 0000000..8789992
--- /dev/null
+++ b/services/tests/servicestests/test-apps/SimpleServiceTestApp/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.servicestests.apps.simpleservicetestapp">
+
+ <application>
+ <service android:name=".SimpleService"
+ android:exported="true" />
+ </application>
+
+</manifest>
diff --git a/services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java b/services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java
new file mode 100644
index 0000000..75f71d6
--- /dev/null
+++ b/services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.servicestests.apps.simpleservicetestapp;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.IRemoteCallback;
+import android.os.Process;
+
+public class SimpleService extends Service {
+ private final IRemoteCallback.Stub mBinder = new IRemoteCallback.Stub() {
+ @Override
+ public void sendResult(Bundle bundle) {
+ Process.killProcess(Process.myPid());
+ }
+ };
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index cd0f4f1..1ee71fb 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -5478,7 +5478,7 @@
Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
mService.mNotificationDelegate.grantInlineReplyUriPermission(
- nr.getKey(), uri, nr.sbn.getUid());
+ nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
// Grant permission called for the UID of SystemUI under the target user ID
verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
@@ -5487,6 +5487,27 @@
}
@Test
+ public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception {
+ NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
+ waitForIdle();
+
+ // No notifications exist for the given record
+ StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
+ assertEquals(0, notifsBefore.length);
+
+ Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
+ int uid = 0; // sysui on primary user
+
+ mService.mNotificationDelegate.grantInlineReplyUriPermission(
+ nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
+
+ // Grant permission still called if no NotificationRecord exists for the given key
+ verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
+ eq(nr.sbn.getUid()), eq(nr.sbn.getPackageName()), eq(uri), anyInt(), anyInt(),
+ eq(nr.sbn.getUserId()));
+ }
+
+ @Test
public void testGrantInlineReplyUriPermission_userAll() throws Exception {
// generate a NotificationRecord for USER_ALL to make sure it's converted into USER_SYSTEM
NotificationRecord nr =
@@ -5504,7 +5525,7 @@
Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
mService.mNotificationDelegate.grantInlineReplyUriPermission(
- nr.getKey(), uri, nr.sbn.getUid());
+ nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
// Target user for the grant is USER_ALL instead of USER_SYSTEM
verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
@@ -5531,7 +5552,7 @@
Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
int uid = 0; // sysui on primary user
- int otherUserUid = (otherUserId * 100000) + 1; // SystemUI as a different user
+ int otherUserUid = (otherUserId * 100000) + 1; // sysui as a different user
String sysuiPackage = "sysui";
final String[] sysuiPackages = new String[] { sysuiPackage };
when(mPackageManager.getPackagesForUid(uid)).thenReturn(sysuiPackages);
@@ -5541,7 +5562,8 @@
when(mPackageManager.getPackageUid(sysuiPackage, 0, otherUserId))
.thenReturn(otherUserUid);
- mService.mNotificationDelegate.grantInlineReplyUriPermission(nr.getKey(), uri, uid);
+ mService.mNotificationDelegate.grantInlineReplyUriPermission(
+ nr.getKey(), uri, nr.sbn.getUser(), nr.sbn.getPackageName(), uid);
// Target user for the grant is USER_ALL instead of USER_SYSTEM
verify(mUgm, times(1)).grantUriPermissionFromOwner(any(),
@@ -5550,22 +5572,64 @@
}
@Test
- public void testGrantInlineReplyUriPermission_noRecordExists() throws Exception {
- NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel);
- waitForIdle();
+ public void testClearInlineReplyUriPermission_uriRecordExists() throws Exception {
+ NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
+ reset(mPackageManager);
- // No notifications exist for the given record
- StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
- assertEquals(0, notifsBefore.length);
+ Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
+ Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
- Uri uri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
- int uid = 0; // sysui on primary user
+ // create an inline record with two uris in it
+ mService.mNotificationDelegate.grantInlineReplyUriPermission(
+ nr.getKey(), uri1, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
+ mService.mNotificationDelegate.grantInlineReplyUriPermission(
+ nr.getKey(), uri2, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
- mService.mNotificationDelegate.grantInlineReplyUriPermission(nr.getKey(), uri, uid);
+ InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
+ assertNotNull(record); // record exists
+ assertEquals(record.getUris().size(), 2); // record has two uris in it
- // Grant permission not called if no record exists for the given key
- verify(mUgm, times(0)).grantUriPermissionFromOwner(any(), anyInt(), any(),
- eq(uri), anyInt(), anyInt(), anyInt());
+ mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), nr.sbn.getUid());
+
+ // permissionOwner destroyed
+ verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
+ eq(record.getPermissionOwner()), eq(null), eq(~0), eq(nr.getUserId()));
+ }
+
+
+ @Test
+ public void testClearInlineReplyUriPermission_noUriRecordExists() throws Exception {
+ NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel, 0);
+ reset(mPackageManager);
+
+ mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), nr.sbn.getUid());
+
+ // no permissionOwner destroyed
+ verify(mUgmInternal, times(0)).revokeUriPermissionFromOwner(
+ any(), eq(null), eq(~0), eq(nr.getUserId()));
+ }
+
+ @Test
+ public void testClearInlineReplyUriPermission_userAll() throws Exception {
+ NotificationRecord nr = generateNotificationRecord(mTestNotificationChannel,
+ UserHandle.USER_ALL);
+ reset(mPackageManager);
+
+ Uri uri1 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 1);
+ Uri uri2 = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 2);
+
+ // create an inline record a uri in it
+ mService.mNotificationDelegate.grantInlineReplyUriPermission(
+ nr.getKey(), uri1, nr.sbn.getUser(), nr.sbn.getPackageName(), nr.sbn.getUid());
+
+ InlineReplyUriRecord record = mService.mInlineReplyRecordsByKey.get(nr.getKey());
+ assertNotNull(record); // record exists
+
+ mService.mNotificationDelegate.clearInlineReplyUriPermissions(nr.getKey(), nr.sbn.getUid());
+
+ // permissionOwner destroyed for USER_SYSTEM, not USER_ALL
+ verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(
+ eq(record.getPermissionOwner()), eq(null), eq(~0), eq(USER_SYSTEM));
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 80439cf..a1322b9 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -62,7 +62,6 @@
import android.provider.Settings;
import android.provider.Settings.Global;
import android.provider.Settings.Secure;
-
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.TestableContentResolver;
import android.util.ArrayMap;
@@ -162,11 +161,11 @@
when(testContentProvider.getIContentProvider()).thenReturn(mTestIContentProvider);
contentResolver.addProvider(TEST_AUTHORITY, testContentProvider);
- when(mTestIContentProvider.canonicalize(any(), eq(SOUND_URI)))
+ when(mTestIContentProvider.canonicalize(any(), any(), eq(SOUND_URI)))
.thenReturn(CANONICAL_SOUND_URI);
- when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI)))
+ when(mTestIContentProvider.canonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
.thenReturn(CANONICAL_SOUND_URI);
- when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI)))
+ when(mTestIContentProvider.uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
.thenReturn(SOUND_URI);
mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0,
@@ -465,7 +464,7 @@
// Testing that in restore we are given the canonical version
loadStreamXml(baos, true, UserHandle.USER_SYSTEM);
- verify(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI));
+ verify(mTestIContentProvider).uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
}
@Test
@@ -475,11 +474,11 @@
.appendQueryParameter("title", "Test")
.appendQueryParameter("canonical", "1")
.build();
- when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI)))
+ when(mTestIContentProvider.canonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
.thenReturn(canonicalBasedOnLocal);
- when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI)))
+ when(mTestIContentProvider.uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
.thenReturn(localUri);
- when(mTestIContentProvider.uncanonicalize(any(), eq(canonicalBasedOnLocal)))
+ when(mTestIContentProvider.uncanonicalize(any(), any(), eq(canonicalBasedOnLocal)))
.thenReturn(localUri);
NotificationChannel channel =
@@ -499,9 +498,9 @@
@Test
public void testRestoreXml_withNonExistentCanonicalizedSoundUri() throws Exception {
Thread.sleep(3000);
- when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI)))
+ when(mTestIContentProvider.canonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
.thenReturn(null);
- when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI)))
+ when(mTestIContentProvider.uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
.thenReturn(null);
NotificationChannel channel =
@@ -526,7 +525,7 @@
@Test
public void testRestoreXml_withUncanonicalizedNonLocalSoundUri() throws Exception {
// Not a local uncanonicalized uri, simulating that it fails to exist locally
- when(mTestIContentProvider.canonicalize(any(), eq(SOUND_URI))).thenReturn(null);
+ when(mTestIContentProvider.canonicalize(any(), any(), eq(SOUND_URI))).thenReturn(null);
String id = "id";
String backupWithUncanonicalizedSoundUri = "<ranking version=\"1\">\n"
+ "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
index 2abd340..8774b63 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -132,11 +132,11 @@
when(testContentProvider.getIContentProvider()).thenReturn(mTestIContentProvider);
contentResolver.addProvider(TEST_AUTHORITY, testContentProvider);
- when(mTestIContentProvider.canonicalize(any(), eq(SOUND_URI)))
+ when(mTestIContentProvider.canonicalize(any(), any(), eq(SOUND_URI)))
.thenReturn(CANONICAL_SOUND_URI);
- when(mTestIContentProvider.canonicalize(any(), eq(CANONICAL_SOUND_URI)))
+ when(mTestIContentProvider.canonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
.thenReturn(CANONICAL_SOUND_URI);
- when(mTestIContentProvider.uncanonicalize(any(), eq(CANONICAL_SOUND_URI)))
+ when(mTestIContentProvider.uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
.thenReturn(SOUND_URI);
mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0,
diff --git a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
index 3b336eb..aceed86 100644
--- a/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/slice/PinnedSliceStateTest.java
@@ -12,6 +12,7 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -109,8 +110,8 @@
mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken);
TestableLooper.get(this).processAllMessages();
- verify(mIContentProvider).call(anyString(), anyString(), eq(SliceProvider.METHOD_PIN),
- eq(null), argThat(b -> {
+ verify(mIContentProvider).call(anyString(), nullable(String.class), anyString(),
+ eq(SliceProvider.METHOD_PIN), eq(null), argThat(b -> {
assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI));
return true;
}));
@@ -167,8 +168,8 @@
// Throw exception when trying to pin
doAnswer(invocation -> {
throw new Exception("Pin failed");
- }).when(mIContentProvider).call(
- anyString(), anyString(), anyString(), eq(null), any());
+ }).when(mIContentProvider).call(anyString(), nullable(String.class), anyString(),
+ anyString(), eq(null), any());
TestableLooper.get(this).processAllMessages();
@@ -176,8 +177,8 @@
mPinnedSliceManager.pin("pkg", FIRST_SPECS, mToken);
TestableLooper.get(this).processAllMessages();
- verify(mIContentProvider).call(anyString(), anyString(), eq(SliceProvider.METHOD_PIN),
- eq(null), argThat(b -> {
+ verify(mIContentProvider).call(anyString(), nullable(String.class), anyString(),
+ eq(SliceProvider.METHOD_PIN), eq(null), argThat(b -> {
assertEquals(TEST_URI, b.getParcelable(SliceProvider.EXTRA_BIND_URI));
return true;
}));
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 03367db..7c867b6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -149,9 +149,7 @@
public void testOnActivityLaunchFinished() {
onActivityLaunched();
- mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
- SystemClock.elapsedRealtimeNanos());
-
+ notifyTransitionStarting();
notifyWindowsDrawn(mTopActivity);
verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mTopActivity), anyLong());
@@ -159,10 +157,10 @@
}
@Test
- public void testOnActivityLaunchCancelled() {
+ public void testOnActivityLaunchCancelled_hasDrawn() {
onActivityLaunched();
- mTopActivity.mDrawn = true;
+ mTopActivity.visible = mTopActivity.mDrawn = true;
// Cannot time already-visible activities.
mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT, mTopActivity);
@@ -172,6 +170,28 @@
}
@Test
+ public void testOnActivityLaunchCancelled_finishedBeforeDrawn() {
+ mTopActivity.visible = mTopActivity.mDrawn = true;
+
+ // Suppress resume when creating the record because we want to notify logger manually.
+ mSupervisor.beginDeferResume();
+ // Create an activity with different process that meets process switch.
+ final ActivityRecord noDrawnActivity = new ActivityBuilder(mService)
+ .setTask(mTopActivity.getTaskRecord())
+ .setProcessName("other")
+ .build();
+ mSupervisor.readyToResume();
+
+ mActivityMetricsLogger.notifyActivityLaunching(noDrawnActivity.intent);
+ mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS, noDrawnActivity);
+
+ noDrawnActivity.destroyIfPossible("test");
+ mActivityMetricsLogger.notifyVisibilityChanged(noDrawnActivity);
+
+ verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(noDrawnActivity));
+ }
+
+ @Test
public void testOnReportFullyDrawn() {
onActivityLaunched();
@@ -184,16 +204,21 @@
private void onActivityLaunchedTrampoline() {
onIntentStarted();
- mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS, mTopActivity);
-
- verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mTopActivity), anyInt());
-
- // A second, distinct, activity launch is coalesced into the the current app launch sequence
mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS, mTrampolineActivity);
+ verifyAsync(mLaunchObserver).onActivityLaunched(eqProto(mTrampolineActivity), anyInt());
+
+ // A second, distinct, activity launch is coalesced into the current app launch sequence.
+ mActivityMetricsLogger.notifyActivityLaunched(START_SUCCESS, mTopActivity);
+
verifyNoMoreInteractions(mLaunchObserver);
}
+ private void notifyTransitionStarting() {
+ mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
+ SystemClock.elapsedRealtimeNanos());
+ }
+
private void notifyWindowsDrawn(ActivityRecord r) {
mActivityMetricsLogger.notifyWindowsDrawn(r.getWindowingMode(),
SystemClock.elapsedRealtimeNanos());
@@ -203,15 +228,12 @@
public void testOnActivityLaunchFinishedTrampoline() {
onActivityLaunchedTrampoline();
- mActivityMetricsLogger.notifyTransitionStarting(new SparseIntArray(),
- SystemClock.elapsedRealtimeNanos());
-
+ notifyTransitionStarting();
notifyWindowsDrawn(mTrampolineActivity);
notifyWindowsDrawn(mTopActivity);
- verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mTrampolineActivity),
- anyLong());
+ verifyAsync(mLaunchObserver).onActivityLaunchFinished(eqProto(mTopActivity), anyLong());
verifyNoMoreInteractions(mLaunchObserver);
}
@@ -219,12 +241,12 @@
public void testOnActivityLaunchCancelledTrampoline() {
onActivityLaunchedTrampoline();
- mTrampolineActivity.mDrawn = true;
+ mTopActivity.mDrawn = true;
// Cannot time already-visible activities.
- mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT, mTrampolineActivity);
+ mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT, mTopActivity);
- verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mTrampolineActivity));
+ verifyAsync(mLaunchObserver).onActivityLaunchCancelled(eqProto(mTopActivity));
verifyNoMoreInteractions(mLaunchObserver);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 99ecdcb..2ce37f1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -53,8 +53,6 @@
import static com.android.server.wm.ActivityStack.ActivityState.STARTED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_INVISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
@@ -136,13 +134,13 @@
@Test
public void testStackCleanupOnActivityRemoval() {
- mTask.mTask.removeChild(mActivity);
+ mTask.removeChild(mActivity);
verify(mStack, times(1)).onActivityRemovedFromStack(any());
}
@Test
public void testStackCleanupOnTaskRemoval() {
- mStack.removeTask(mTask, null /*reason*/, REMOVE_TASK_MODE_MOVING);
+ mStack.removeChild(mTask, null /*reason*/);
// Stack should be gone on task removal.
assertNull(mService.mRootActivityContainer.getStack(mStack.mStackId));
}
@@ -325,7 +323,7 @@
: ORIENTATION_PORTRAIT;
mTask.onRequestedOverrideConfigurationChanged(newConfig);
- doReturn(true).when(mTask.mTask).isDragResizing();
+ doReturn(true).when(mTask).isDragResizing();
mActivity.mRelaunchReason = ActivityTaskManagerService.RELAUNCH_REASON_NONE;
@@ -382,7 +380,7 @@
}
// Mimic the behavior that display doesn't handle app's requested orientation.
- final DisplayContent dc = mTask.mTask.getDisplayContent();
+ final DisplayContent dc = mTask.getDisplayContent();
doReturn(false).when(dc).onDescendantOrientationChanged(any(), any());
doReturn(false).when(dc).handlesOrientationChangeFromDescendant();
@@ -836,6 +834,14 @@
// Set process to 'null' to allow immediate removal, but don't call mActivity.setProcess() -
// this will cause NPE when updating task's process.
mActivity.app = null;
+
+ // Put a visible activity on top, so the finishing activity doesn't have to wait until the
+ // next activity reports idle to destroy it.
+ final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
+ topActivity.visible = true;
+ topActivity.nowVisible = true;
+ topActivity.setState(RESUMED, "test");
+
assertEquals("Activity outside of task/stack cannot be finished", FINISH_RESULT_REMOVED,
mActivity.finishIfPossible("test", false /* oomAdj */));
assertTrue(mActivity.finishing);
@@ -1131,8 +1137,11 @@
// Add another stack to become focused and make the activity there visible. This way it
// simulates finishing in non-focused stack in split-screen.
final ActivityStack stack = new StackBuilder(mRootActivityContainer).build();
- stack.getChildAt(0).getChildAt(0).nowVisible = true;
- stack.getChildAt(0).getChildAt(0).visible = true;
+ final ActivityRecord focusedActivity = stack.getChildAt(0).getChildAt(0);
+ focusedActivity.nowVisible = true;
+ focusedActivity.visible = true;
+ focusedActivity.setState(RESUMED, "test");
+ stack.mResumedActivity = focusedActivity;
topActivity.completeFinishing("test");
@@ -1163,7 +1172,7 @@
// Empty the home stack.
final ActivityStack homeStack = mActivity.getDisplay().getHomeStack();
for (TaskRecord t : homeStack.getAllTasks()) {
- homeStack.removeTask(t, "test", REMOVE_TASK_MODE_DESTROYING);
+ homeStack.removeChild(t, "test");
}
mActivity.finishing = true;
doReturn(false).when(mRootActivityContainer).resumeFocusedStacksTopActivities();
@@ -1180,6 +1189,30 @@
}
/**
+ * Verify that complete finish request for visible activity must resume next home stack before
+ * destroying it immediately if it is the last running activity on a display with a home stack.
+ * We must wait for home activity to come up to avoid a black flash in this case.
+ */
+ @Test
+ public void testCompleteFinishing_lastActivityAboveEmptyHomeStack() {
+ // Empty the home stack.
+ final ActivityStack homeStack = mActivity.getDisplay().getHomeStack();
+ for (TaskRecord t : homeStack.getAllTasks()) {
+ homeStack.removeChild(t, "test");
+ }
+ mActivity.finishing = true;
+ spyOn(mStack);
+
+ // Try to finish the last activity above the home stack.
+ mActivity.completeFinishing("test");
+
+ // Verify that the activity is not destroyed immediately, but waits for next one to come up.
+ verify(mActivity, never()).destroyImmediately(eq(true) /* removeFromApp */, anyString());
+ assertEquals(FINISHING, mActivity.getState());
+ assertTrue(mActivity.mStackSupervisor.mFinishingActivities.contains(mActivity));
+ }
+
+ /**
* Test that the activity will be moved to destroying state and the message to destroy will be
* sent to the client.
*/
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index fcebb81..cc0cc3f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -38,7 +38,6 @@
import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_INVISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
@@ -93,21 +92,6 @@
}
@Test
- public void testEmptyTaskCleanupOnRemove() {
- assertNotNull(mTask.getTask());
- mStack.removeTask(mTask, "testEmptyTaskCleanupOnRemove", REMOVE_TASK_MODE_DESTROYING);
- assertNull(mTask.getTask());
- }
-
- @Test
- public void testOccupiedTaskCleanupOnRemove() {
- final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
- assertNotNull(mTask.getTask());
- mStack.removeTask(mTask, "testOccupiedTaskCleanupOnRemove", REMOVE_TASK_MODE_DESTROYING);
- assertNotNull(mTask.getTask());
- }
-
- @Test
public void testResumedActivity() {
final ActivityRecord r = new ActivityBuilder(mService).setTask(mTask).build();
assertNull(mStack.getResumedActivity());
@@ -996,27 +980,6 @@
}
@Test
- public void testAdjustFocusedStackToHomeWhenNoActivity() {
- final ActivityStack homeStask = mDefaultDisplay.getHomeStack();
- TaskRecord homeTask = homeStask.topTask();
- if (homeTask == null) {
- // Create home task if there isn't one.
- homeTask = new TaskBuilder(mSupervisor).setStack(homeStask).build();
- }
-
- final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
- mStack.moveToFront("testAdjustFocusedStack");
-
- // Simulate that home activity has not been started or is force-stopped.
- homeStask.removeTask(homeTask, "testAdjustFocusedStack", REMOVE_TASK_MODE_DESTROYING);
-
- // Finish the only activity.
- topActivity.finishIfPossible("testAdjustFocusedStack", false /* oomAdj */);
- // Although home stack is empty, it should still be the focused stack.
- assertEquals(homeStask, mDefaultDisplay.getFocusedStack());
- }
-
- @Test
public void testWontFinishHomeStackImmediately() {
final ActivityStack homeStack = createStackForShouldBeVisibleTest(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index ace5d4e..a28bbb6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -715,7 +715,7 @@
if (startedActivity != null && startedActivity.getTaskRecord() != null) {
// Remove the activity so it doesn't interfere with with subsequent activity launch
// tests from this method.
- startedActivity.getTaskRecord().mTask.removeChild(startedActivity);
+ startedActivity.getTaskRecord().removeChild(startedActivity);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 7b7e6e7..399f283 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -16,11 +16,16 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import android.app.Activity;
+import android.graphics.Rect;
+import android.view.WindowContainerTransaction;
import androidx.test.filters.MediumTest;
@@ -58,5 +63,18 @@
mService.finishActivity(activity.appToken, 0 /* resultCode */,
null /* resultData */, Activity.DONT_FINISH_TASK_WITH_ACTIVITY));
}
+
+ @Test
+ public void testTaskTransaction() {
+ removeGlobalMinSizeRestriction();
+ final ActivityStack stack = new StackBuilder(mRootActivityContainer)
+ .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
+ final TaskRecord task = stack.topTask();
+ WindowContainerTransaction t = new WindowContainerTransaction();
+ Rect newBounds = new Rect(10, 10, 100, 100);
+ t.setBounds(task.mRemoteToken, new Rect(10, 10, 100, 100));
+ mService.applyContainerTransaction(t);
+ assertEquals(newBounds, task.getBounds());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
index 80f0851..1db8f1b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTestsBase.java
@@ -118,7 +118,8 @@
private ComponentName mComponent;
private String mTargetActivity;
private TaskRecord mTaskRecord;
- private int mUid;
+ private String mProcessName = "name";
+ private int mUid = 12345;
private boolean mCreateTask;
private ActivityStack mStack;
private int mActivityFlags;
@@ -175,6 +176,11 @@
return this;
}
+ ActivityBuilder setProcessName(String name) {
+ mProcessName = name;
+ return this;
+ }
+
ActivityBuilder setUid(int uid) {
mUid = uid;
return this;
@@ -235,6 +241,7 @@
aInfo.applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
aInfo.applicationInfo.packageName = mComponent.getPackageName();
aInfo.applicationInfo.uid = mUid;
+ aInfo.processName = mProcessName;
aInfo.packageName = mComponent.getPackageName();
if (mTargetActivity != null) {
aInfo.targetActivity = mTargetActivity;
@@ -262,13 +269,13 @@
// fullscreen value is normally read from resources in ctor, so for testing we need
// to set it somewhere else since we can't mock resources.
doReturn(true).when(activity).occludesParent();
- activity.setTask(mTaskRecord);
+ mTaskRecord.addChild(activity);
// Make visible by default...
activity.setHidden(false);
}
final WindowProcessController wpc = new WindowProcessController(mService,
- mService.mContext.getApplicationInfo(), "name", 12345,
+ mService.mContext.getApplicationInfo(), mProcessName, mUid,
UserHandle.getUserId(12345), mock(Object.class),
mock(WindowProcessListener.class));
wpc.setThread(mock(IApplicationThread.class));
@@ -369,15 +376,13 @@
final TaskRecord task = new TaskRecord(mSupervisor.mService, mTaskId, aInfo,
intent /*intent*/, mVoiceSession, null /*_voiceInteractor*/,
- null /*taskDescription*/);
+ null /*taskDescription*/, mStack);
spyOn(task);
task.mUserId = mUserId;
if (mStack != null) {
mStack.moveToFront("test");
- mStack.addTask(task, true, "creating test task");
- task.createTask(true, true);
- spyOn(task.mTask);
+ mStack.addChild(task, true, true);
}
return task;
diff --git a/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
index 77f9f04..b6eaab7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
@@ -21,6 +21,7 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyZeroInteractions;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -69,8 +70,8 @@
activity1.startAnimation(activity1.getPendingTransaction(), mAdapter, false /* hidden */);
activity2.startAnimation(activity1.getPendingTransaction(), mAdapter, false /* hidden */);
- assertTrue(activity1.isSelfAnimating());
- assertTrue(activity2.isSelfAnimating());
+ assertTrue(activity1.isAnimating(TRANSITION));
+ assertTrue(activity2.isAnimating(TRANSITION));
// Make sure that first animation finish is deferred, second one is not deferred, and first
// one gets cancelled.
@@ -92,8 +93,8 @@
window1.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
window2.startAnimation(window1.getPendingTransaction(), mAdapter, false /* hidden */);
- assertTrue(window1.isSelfAnimating());
- assertTrue(window2.isSelfAnimating());
+ assertTrue(window1.isAnimating(TRANSITION));
+ assertTrue(window2.isAnimating(TRANSITION));
// Make sure that first animation finish is deferred, and removing the second window stops
// finishes all pending deferred finishings.
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index 1fb6a56..7b9be3d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -62,7 +62,7 @@
public void setUpOnDisplay(DisplayContent dc) {
mActivity = createTestActivityRecord(dc, WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD);
mTask = mActivity.getTask();
- mStack = mTask.mStack;
+ mStack = mTask.getTaskStack();
// Set a remote animator with snapshot disabled. Snapshots don't work in wmtests.
RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
@@ -165,7 +165,7 @@
// setup currently defaults to no snapshot.
setUpOnDisplay(mDisplayContent);
- mTask.mTaskRecord.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
assertEquals(1, mDisplayContent.mChangingApps.size());
assertTrue(mActivity.isInChangeTransition());
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 06afce2..5f42d23 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -147,8 +147,8 @@
// Make sure each display is in animating stage.
assertTrue(dc1.mOpeningApps.size() > 0);
assertTrue(dc2.mClosingApps.size() > 0);
- assertTrue(dc1.isAppAnimating());
- assertTrue(dc2.isAppAnimating());
+ assertTrue(dc1.isAppTransitioning());
+ assertTrue(dc2.isAppTransitioning());
}
@Test
@@ -219,10 +219,10 @@
assertTrue(dc.mClosingApps.size() > 0);
// Make sure window is in animating stage before freeze, and cancel after freeze.
- assertTrue(dc.isAppAnimating());
+ assertTrue(dc.isAppTransitioning());
assertFalse(runner.mCancelled);
dc.mAppTransition.freeze();
- assertFalse(dc.isAppAnimating());
+ assertFalse(dc.isAppTransitioning());
assertTrue(runner.mCancelled);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 2f0486d..d33dbd1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -48,7 +48,7 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import android.content.res.Configuration;
@@ -63,7 +63,6 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mockito;
/**
* Tests for the {@link ActivityRecord} class.
@@ -209,9 +208,11 @@
@Test
public void testSizeCompatBounds() {
+ // TODO(task-merge): Move once Task is merged into TaskRecord
+ final TaskRecord tr = (TaskRecord) mTask;
// Disable the real configuration resolving because we only simulate partial flow.
// TODO: Have test use full flow.
- doNothing().when(mTask.mTaskRecord).computeConfigResourceOverrides(any(), any());
+ doNothing().when(tr).computeConfigResourceOverrides(any(), any());
final Rect fixedBounds = mActivity.getRequestedOverrideConfiguration().windowConfiguration
.getBounds();
fixedBounds.set(0, 0, 1200, 1600);
@@ -337,11 +338,9 @@
mDisplayContent.getDisplayRotation().setFixedToUserRotation(
DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
-
- mTask.mTaskRecord = Mockito.mock(TaskRecord.class, RETURNS_DEEP_STUBS);
+ reset(mTask);
mActivity.reportDescendantOrientationChangeIfNeeded();
-
- verify(mTask.mTaskRecord).onConfigurationChanged(any(Configuration.class));
+ verify(mTask).onConfigurationChanged(any(Configuration.class));
}
@Test
@@ -451,6 +450,7 @@
@Test
public void testTransitionAnimationBounds() {
+ removeGlobalMinSizeRestriction();
final Rect stackBounds = new Rect(0, 0, 1000, 600);
final Rect taskBounds = new Rect(100, 400, 600, 800);
mStack.setBounds(stackBounds);
@@ -458,16 +458,16 @@
// Check that anim bounds for freeform window match task bounds
mTask.setWindowingMode(WINDOWING_MODE_FREEFORM);
- assertEquals(taskBounds, mActivity.getAnimationBounds(STACK_CLIP_NONE));
+ assertEquals(mTask.getBounds(), mActivity.getAnimationBounds(STACK_CLIP_NONE));
// STACK_CLIP_AFTER_ANIM should use task bounds since they will be clipped by
// bounds animation layer.
mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
- assertEquals(taskBounds, mActivity.getAnimationBounds(STACK_CLIP_AFTER_ANIM));
+ assertEquals(mTask.getBounds(), mActivity.getAnimationBounds(STACK_CLIP_AFTER_ANIM));
// STACK_CLIP_BEFORE_ANIM should use stack bounds since it won't be clipped later.
mTask.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
- assertEquals(stackBounds, mActivity.getAnimationBounds(STACK_CLIP_BEFORE_ANIM));
+ assertEquals(mStack.getBounds(), mActivity.getAnimationBounds(STACK_CLIP_BEFORE_ANIM));
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 01489c6..bd137fb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -119,7 +119,7 @@
waitUntilHandlersIdle();
exitingApp.mIsExiting = true;
- exitingApp.getTask().mStack.mExitingActivities.add(exitingApp);
+ exitingApp.getTask().getTaskStack().mExitingActivities.add(exitingApp);
assertForAllWindowsOrder(Arrays.asList(
mWallpaperWindow,
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 2a3731a..67b7a66 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -24,6 +24,7 @@
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
+import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
@@ -56,15 +57,23 @@
import android.view.DisplayInfo;
import android.view.WindowManager;
+import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.utils.WmDisplayCutout;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+/**
+ * Tests for the {@link DisplayPolicy} class.
+ *
+ * Build/Install/Run:
+ * atest WmTests:DisplayPolicyLayoutTests
+ */
@SmallTest
@Presubmit
@RunWith(WindowTestRunner.class)
@@ -93,6 +102,12 @@
attrs.format = PixelFormat.TRANSLUCENT;
}
+ @After
+ public void tearDown() {
+ PolicyControl.setFilters("");
+ mWindow.getDisplayContent().mInputMethodTarget = null;
+ }
+
public void setRotation(int rotation) {
mRotation = rotation;
updateDisplayFrames();
@@ -393,6 +408,105 @@
assertInsetBy(mWindow.getDisplayFrameLw(), 0, 0, 0, 0);
}
+ @FlakyTest(bugId = 129711077)
+ @Test
+ public void layoutWindowLw_withImmersive_SoftInputAdjustResize() {
+ synchronized (mWm.mGlobalLock) {
+ mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
+ mWindow.mAttrs.flags = 0;
+ mWindow.mAttrs.systemUiVisibility =
+ SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+
+ addWindow(mWindow);
+
+ mWindow.getDisplayContent().mInputMethodTarget = mWindow;
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mFrames.mContent.bottom = mFrames.mVoiceContent.bottom = INPUT_METHOD_WINDOW_TOP;
+ mFrames.mCurrent.bottom = INPUT_METHOD_WINDOW_TOP;
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ int bottomInset = mFrames.mDisplayHeight - INPUT_METHOD_WINDOW_TOP;
+ assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(), 0, 0);
+ assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, bottomInset);
+ }
+ }
+
+ @FlakyTest(bugId = 129711077)
+ @Test
+ public void layoutWindowLw_withImmersive_SoftInputAdjustNothing() {
+ synchronized (mWm.mGlobalLock) {
+ mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_NOTHING;
+ mWindow.mAttrs.flags = 0;
+ mWindow.mAttrs.systemUiVisibility =
+ SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+
+ addWindow(mWindow);
+
+ mWindow.getDisplayContent().mInputMethodTarget = mWindow;
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mFrames.mContent.bottom = mFrames.mVoiceContent.bottom = INPUT_METHOD_WINDOW_TOP;
+ mFrames.mCurrent.bottom = INPUT_METHOD_WINDOW_TOP;
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(), 0, 0);
+ assertInsetByTopBottom(mWindow.getVisibleFrameLw(), 0, 0);
+ }
+ }
+
+ @FlakyTest(bugId = 129711077)
+ @Test
+ public void layoutWindowLw_withForceImmersive_fullscreen() {
+ synchronized (mWm.mGlobalLock) {
+ mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
+ mWindow.mAttrs.flags = 0;
+ mWindow.mAttrs.systemUiVisibility = 0;
+ PolicyControl.setFilters(PolicyControl.NAME_IMMERSIVE_FULL + "=*");
+
+ addWindow(mWindow);
+
+ mWindow.getDisplayContent().mInputMethodTarget = mWindow;
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mFrames.mContent.bottom = mFrames.mVoiceContent.bottom = INPUT_METHOD_WINDOW_TOP;
+ mFrames.mCurrent.bottom = INPUT_METHOD_WINDOW_TOP;
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ int bottomInset = mFrames.mDisplayHeight - INPUT_METHOD_WINDOW_TOP;
+ assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(), 0, 0);
+ assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, bottomInset);
+ }
+ }
+
+ @FlakyTest(bugId = 129711077)
+ @Test
+ public void layoutWindowLw_withForceImmersive_nonFullscreen() {
+ synchronized (mWm.mGlobalLock) {
+ mWindow.mAttrs.softInputMode = SOFT_INPUT_ADJUST_RESIZE;
+ mWindow.mAttrs.flags = 0;
+ mWindow.mAttrs.systemUiVisibility = 0;
+ mWindow.mAttrs.width = DISPLAY_WIDTH / 2;
+ mWindow.mAttrs.height = DISPLAY_HEIGHT / 2;
+ PolicyControl.setFilters(PolicyControl.NAME_IMMERSIVE_FULL + "=*");
+
+ addWindow(mWindow);
+
+ mWindow.getDisplayContent().mInputMethodTarget = mWindow;
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mFrames.mContent.bottom = mFrames.mVoiceContent.bottom = INPUT_METHOD_WINDOW_TOP;
+ mFrames.mCurrent.bottom = INPUT_METHOD_WINDOW_TOP;
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ int bottomInset = mFrames.mDisplayHeight - INPUT_METHOD_WINDOW_TOP;
+ assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, bottomInset);
+ assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, bottomInset);
+ assertInsetByTopBottom(mWindow.getVisibleFrameLw(), STATUS_BAR_HEIGHT, bottomInset);
+ }
+ }
+
@Test
public void layoutHint_appWindow() {
// Initialize DisplayFrames
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
index 2933b4a..d4558dc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
@@ -62,6 +62,7 @@
static final int STATUS_BAR_HEIGHT = 10;
static final int NAV_BAR_HEIGHT = 15;
static final int DISPLAY_CUTOUT_HEIGHT = 8;
+ static final int INPUT_METHOD_WINDOW_TOP = 585;
DisplayPolicy mDisplayPolicy;
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index 8c2ae5a..55947ae 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -178,11 +178,14 @@
@Test
public void testShowTransientBars_topCanBeTransient_appGetsTopFakeControl() {
+ // Adding app window before setting source visibility is to prevent the visibility from
+ // being cleared by InsetsSourceProvider.updateVisibility.
+ final WindowState app = addWindow(TYPE_APPLICATION, "app");
+
addWindow(TYPE_STATUS_BAR, "topBar")
.getControllableInsetProvider().getSource().setVisible(false);
addWindow(TYPE_NAVIGATION_BAR, "navBar")
.getControllableInsetProvider().getSource().setVisible(true);
- final WindowState app = addWindow(TYPE_APPLICATION, "app");
final InsetsPolicy policy = mDisplayContent.getInsetsPolicy();
policy.updateBarControlTarget(app);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index cc598ff..69091c6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -885,7 +885,7 @@
final int taskId = task.mTaskId;
mRecentTasks.add(task);
// Only keep the task in RecentTasks.
- task.removeWindowContainer();
+ task.removeIfPossible();
mStack.remove();
// The following APIs should not restore task from recents to the active list.
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
index 839ddb2..ca8f535 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -196,9 +196,6 @@
doReturn(app).when(mService).getProcessController(eq(recentActivity.processName), anyInt());
ClientLifecycleManager lifecycleManager = mService.getLifecycleManager();
doNothing().when(lifecycleManager).scheduleTransaction(any());
- AppWarnings appWarnings = mService.getAppWarningsLocked();
- spyOn(appWarnings);
- doNothing().when(appWarnings).onStartActivity(any());
startRecentsActivity();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index aa97de72..63f70c0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -36,7 +36,6 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
-import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.RootActivityContainer.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
@@ -272,8 +271,7 @@
assertTrue(pinnedActivity.isFocusable());
// Without the overridding activity, stack should not be focusable.
- pinnedStack.removeTask(pinnedActivity.getTaskRecord(), "testFocusability",
- REMOVE_TASK_MODE_DESTROYING);
+ pinnedStack.removeChild(pinnedActivity.getTaskRecord(), "testFocusability");
assertFalse(pinnedStack.isFocusable());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index fa1f435..ad1d1af 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -437,6 +437,10 @@
spyOn(getLockTaskController());
spyOn(getTaskChangeNotificationController());
initRootActivityContainerMocks();
+
+ AppWarnings appWarnings = getAppWarningsLocked();
+ spyOn(appWarnings);
+ doNothing().when(appWarnings).onStartActivity(any());
}
void initRootActivityContainerMocks() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
index df55b39..9275512b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
@@ -66,7 +66,6 @@
private int mMinVisibleWidth;
private int mMinVisibleHeight;
private TaskPositioner mPositioner;
- private WindowState mWindow;
@Before
public void setUp() {
@@ -79,18 +78,18 @@
// This should be the same calculation as the TaskPositioner uses.
mMinVisibleWidth = dipToPixel(MINIMUM_VISIBLE_WIDTH_IN_DP, dm);
mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, dm);
+ removeGlobalMinSizeRestriction();
- mPositioner = new TaskPositioner(mWm, mock(IActivityTaskManager.class));
- mPositioner.register(mDisplayContent);
+ WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "window");
+ mPositioner = new TaskPositioner(mWm, mWm.mAtmService);
- mWindow = createWindow(null, TYPE_BASE_APPLICATION, "window");
- mPositioner.mTask = mWindow.getTask();
- mWindow.getStack().setWindowingMode(WINDOWING_MODE_FREEFORM);
+ mPositioner.register(mDisplayContent, win);
+
+ win.getStack().setWindowingMode(WINDOWING_MODE_FREEFORM);
}
@After
public void tearDown() {
- mWindow = null;
mPositioner = null;
}
@@ -121,8 +120,8 @@
mPositioner.mTask.setBounds(r, true);
// Start a drag resize starting upper left.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
assertBoundsEquals(r, mPositioner.getWindowDragBounds());
// Drag to a good landscape size.
@@ -148,8 +147,8 @@
mPositioner.getWindowDragBounds());
// Start a drag resize left and see that only the left coord changes..
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, r.left - MOUSE_DELTA_X, midY);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, midY);
// Drag to the left.
mPositioner.resizeDrag(0.0f, midY);
@@ -183,8 +182,8 @@
mPositioner.mTask.setBounds(r, true);
// Drag upper left.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
mPositioner.resizeDrag(0.0f, 0.0f);
assertNotEquals(r.left, mPositioner.getWindowDragBounds().left);
assertEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -192,8 +191,8 @@
assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag upper.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, midX, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */, midX,
+ r.top - MOUSE_DELTA_Y);
mPositioner.resizeDrag(0.0f, 0.0f);
assertEquals(r.left, mPositioner.getWindowDragBounds().left);
assertEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -201,8 +200,8 @@
assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag upper right.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, r.right + MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
+ r.right + MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
mPositioner.resizeDrag(r.right + 100, 0.0f);
assertEquals(r.left, mPositioner.getWindowDragBounds().left);
assertNotEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -210,8 +209,8 @@
assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag right.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, r.right + MOUSE_DELTA_X, midY);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
+ r.right + MOUSE_DELTA_X, midY);
mPositioner.resizeDrag(r.right + 100, 0.0f);
assertEquals(r.left, mPositioner.getWindowDragBounds().left);
assertNotEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -219,8 +218,7 @@
assertEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag bottom right.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */,
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
r.right + MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y);
mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
assertEquals(r.left, mPositioner.getWindowDragBounds().left);
@@ -229,8 +227,8 @@
assertNotEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag bottom.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, midX, r.bottom + MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */, midX,
+ r.bottom + MOUSE_DELTA_Y);
mPositioner.resizeDrag(r.right + 100, r.bottom + 100);
assertEquals(r.left, mPositioner.getWindowDragBounds().left);
assertEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -238,8 +236,8 @@
assertNotEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag bottom left.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, r.left - MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, r.bottom + MOUSE_DELTA_Y);
mPositioner.resizeDrag(0.0f, r.bottom + 100);
assertNotEquals(r.left, mPositioner.getWindowDragBounds().left);
assertEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -247,8 +245,8 @@
assertNotEquals(r.bottom, mPositioner.getWindowDragBounds().bottom);
// Drag left.
- mPositioner.startDrag(mWindow, true /* resizing */,
- false /* preserveOrientation */, r.left - MOUSE_DELTA_X, midY);
+ mPositioner.startDrag(true /* resizing */, false /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, midY);
mPositioner.resizeDrag(0.0f, r.bottom + 100);
assertNotEquals(r.left, mPositioner.getWindowDragBounds().left);
assertEquals(r.right, mPositioner.getWindowDragBounds().right);
@@ -265,8 +263,8 @@
final Rect r = new Rect(100, 220, 700, 520);
mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /* resizing */,
- true /* preserveOrientation */, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, true /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
assertBoundsEquals(r, mPositioner.getWindowDragBounds());
// Drag to a good landscape size.
@@ -304,8 +302,8 @@
final int midY = (r.top + r.bottom) / 2;
mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /* resizing */,
- true /* preserveOrientation */, r.left - MOUSE_DELTA_X, midY);
+ mPositioner.startDrag(true /* resizing */, true /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, midY);
// Drag to the left.
mPositioner.resizeDrag(0.0f, midY);
@@ -345,8 +343,8 @@
final int midX = (r.left + r.right) / 2;
mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /*resizing*/,
- true /*preserveOrientation*/, midX, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /*resizing*/, true /*preserveOrientation*/, midX,
+ r.top - MOUSE_DELTA_Y);
// Drag to the left (no change).
mPositioner.resizeDrag(0.0f, r.top);
@@ -381,8 +379,8 @@
final Rect r = new Rect(330, 100, 630, 600);
mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /*resizing*/,
- true /*preserveOrientation*/, r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /*resizing*/, true /*preserveOrientation*/,
+ r.left - MOUSE_DELTA_X, r.top - MOUSE_DELTA_Y);
assertBoundsEquals(r, mPositioner.getWindowDragBounds());
// Drag to a good landscape size.
@@ -415,8 +413,8 @@
final int midY = (r.top + r.bottom) / 2;
mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /* resizing */,
- true /* preserveOrientation */, r.left - MOUSE_DELTA_X, midY);
+ mPositioner.startDrag(true /* resizing */, true /* preserveOrientation */,
+ r.left - MOUSE_DELTA_X, midY);
// Drag to the left.
mPositioner.resizeDrag(0.0f, midY);
@@ -458,8 +456,8 @@
final int midX = (r.left + r.right) / 2;
mPositioner.mTask.setBounds(r, true);
- mPositioner.startDrag(mWindow, true /* resizing */,
- true /* preserveOrientation */, midX, r.top - MOUSE_DELTA_Y);
+ mPositioner.startDrag(true /* resizing */, true /* preserveOrientation */, midX,
+ r.top - MOUSE_DELTA_Y);
// Drag to the left (no change).
mPositioner.resizeDrag(0.0f, r.top);
@@ -493,10 +491,7 @@
+ ") " + Log.getStackTraceString(new Throwable()));
}
}
- assertEquals("left", expected.left, actual.left);
- assertEquals("right", expected.right, actual.right);
- assertEquals("top", expected.top, actual.top);
- assertEquals("bottom", expected.bottom, actual.bottom);
+ assertEquals(expected, actual);
}
@FlakyTest(bugId = 129492888)
@@ -504,7 +499,7 @@
public void testFinishingMovingWhenBinderDied() {
spyOn(mWm.mTaskPositioningController);
- mPositioner.startDrag(mWindow, false, false, 0 /* startX */, 0 /* startY */);
+ mPositioner.startDrag(false, false, 0 /* startX */, 0 /* startY */);
verify(mWm.mTaskPositioningController, never()).finishTaskPositioning();
mPositioner.binderDied();
verify(mWm.mTaskPositioningController).finishTaskPositioning();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
index f8d49ad..d2342f0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositioningControllerTests.java
@@ -66,7 +66,8 @@
any(InputChannel.class))).thenReturn(true);
mWindow = createWindow(null, TYPE_BASE_APPLICATION, "window");
- mWindow.getTask().setResizeable(RESIZE_MODE_RESIZEABLE);
+ // TODO(task-merge): Remove cast.
+ ((TaskRecord) mWindow.getTask()).setResizeMode(RESIZE_MODE_RESIZEABLE);
mWindow.mInputChannel = new InputChannel();
mWm.mWindowMap.put(mWindow.mClient.asBinder(), mWindow);
doReturn(mock(InputMonitor.class)).when(mDisplayContent).getInputMonitor();
@@ -142,7 +143,8 @@
doReturn(mWindow.getTask()).when(content).findTaskForResizePoint(anyInt(), anyInt());
assertNotNull(mWindow.getTask().getTopVisibleAppMainWindow());
- mWindow.getTask().setResizeable(RESIZE_MODE_UNRESIZEABLE);
+ // TODO(task-merge): Remove cast.
+ ((TaskRecord) mWindow.getTask()).setResizeMode(RESIZE_MODE_UNRESIZEABLE);
mTarget.handleTapOutsideTask(content, 0, 0);
// Wait until the looper processes finishTaskPositioning.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index a4e38f1..2cafc96 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -132,7 +132,7 @@
@Test
public void testCopyBaseIntentForTaskInfo() {
final TaskRecord task = createTaskRecord(1);
- task.mTaskDescription = new ActivityManager.TaskDescription();
+ task.setTaskDescription(new ActivityManager.TaskDescription());
final TaskInfo info = task.getTaskInfo();
// The intent of info should be a copy so assert that they are different instances.
@@ -348,10 +348,12 @@
TaskRecord task = stack.getChildAt(0);
ActivityRecord root = task.getTopActivity();
- final WindowContainer parentWindowContainer = mock(WindowContainer.class);
- Mockito.doReturn(parentWindowContainer).when(task.mTask).getParent();
- Mockito.doReturn(true).when(parentWindowContainer)
- .handlesOrientationChangeFromDescendant();
+ final WindowContainer parentWindowContainer =
+ new WindowContainer(mSystemServicesTestRule.getWindowManagerService());
+ spyOn(parentWindowContainer);
+ parentWindowContainer.setBounds(fullScreenBounds);
+ doReturn(parentWindowContainer).when(task).getParent();
+ doReturn(true).when(parentWindowContainer).handlesOrientationChangeFromDescendant();
// Setting app to fixed portrait fits within parent, but TaskRecord shouldn't adjust the
// bounds because its parent says it will handle it at a later time.
@@ -433,7 +435,7 @@
info.targetActivity = targetClassName;
final TaskRecord task = TaskRecord.create(mService, 1 /* taskId */, info, intent,
- null /* taskDescription */);
+ null /* taskDescription */, null /*stack*/);
assertEquals("The alias activity component should be saved in task intent.", aliasClassName,
task.intent.getComponent().getClassName());
@@ -834,8 +836,9 @@
private TaskRecord createTaskRecord(int taskId) {
return new TaskRecord(mService, taskId, new Intent(), null, null, null,
ActivityBuilder.getDefaultComponent(), null, false, false, false, 0, 10050, null,
- new ArrayList<>(), 0, false, null, 0, 0, 0, 0, 0, null, 0, false, false, false, 0,
- 0, null /*ActivityInfo*/, null /*_voiceSession*/, null /*_voiceInteractor*/);
+ 0, false, null, 0, 0, 0, 0, 0, null, 0, false, false, false, 0,
+ 0, null /*ActivityInfo*/, null /*_voiceSession*/, null /*_voiceInteractor*/,
+ null /*stack*/);
}
private static class TestTaskRecordFactory extends TaskRecordFactory {
@@ -843,16 +846,16 @@
@Override
TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent,
- IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
+ Intent intent, IVoiceInteractionSession voiceSession,
+ IVoiceInteractor voiceInteractor, ActivityStack stack) {
mCreated = true;
return null;
}
@Override
TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
- Intent intent,
- ActivityManager.TaskDescription taskDescription) {
+ Intent intent, ActivityManager.TaskDescription taskDescription,
+ ActivityStack stack) {
mCreated = true;
return null;
}
@@ -863,14 +866,14 @@
ComponentName realActivity,
ComponentName origActivity, boolean rootWasReset, boolean autoRemoveRecents,
boolean askedCompatMode, int userId, int effectiveUid, String lastDescription,
- ArrayList<ActivityRecord> activities, long lastTimeMoved,
+ long lastTimeMoved,
boolean neverRelinquishIdentity,
ActivityManager.TaskDescription lastTaskDescription,
int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor,
int callingUid, String callingPackage, int resizeMode,
boolean supportsPictureInPicture,
boolean realActivitySuspended, boolean userSetupComplete, int minWidth,
- int minHeight) {
+ int minHeight, ActivityStack stack) {
mCreated = true;
return null;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
index a66c79c..7897047 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackContainersTests.java
@@ -121,7 +121,7 @@
false /* includingParents */);
// Move the task of {@code mDisplayContent} to top.
- stack.positionChildAt(WindowContainer.POSITION_TOP, task, true /* includingParents */);
+ stack.positionChildAt(WindowContainer.POSITION_TOP, (TaskRecord) task, true /* includingParents */);
final int indexOfDisplayWithPinnedStack = mWm.mRoot.mChildren.indexOf(mDisplayContent);
assertEquals("The testing DisplayContent should be moved to top with task",
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 2fc03c7..a9d0ea1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -23,12 +23,13 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import android.graphics.Rect;
@@ -57,12 +58,12 @@
final Task task2 = createTaskInStack(stack, 1 /* userId */);
// Current user task should be moved to top.
- stack.positionChildAt(WindowContainer.POSITION_TOP, task1, false /* includingParents */);
+ stack.positionChildAt(WindowContainer.POSITION_TOP, (TaskRecord) task1, false /* includingParents */);
assertEquals(stack.mChildren.get(0), task2);
assertEquals(stack.mChildren.get(1), task1);
// Non-current user won't be moved to top.
- stack.positionChildAt(WindowContainer.POSITION_TOP, task2, false /* includingParents */);
+ stack.positionChildAt(WindowContainer.POSITION_TOP, (TaskRecord) task2, false /* includingParents */);
assertEquals(stack.mChildren.get(0), task2);
assertEquals(stack.mChildren.get(1), task1);
}
@@ -111,12 +112,12 @@
public void testStackRemoveImmediately() {
final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- assertEquals(stack, task.mStack);
+ assertEquals(stack, task.getTaskStack());
// Remove stack and check if its child is also removed.
stack.removeImmediately();
assertNull(stack.getDisplayContent());
- assertNull(task.mStack);
+ assertNull(task.getTaskStack());
}
@Test
@@ -132,7 +133,7 @@
assertEquals(0, stack.getChildCount());
assertNull(stack.getDisplayContent());
assertNull(task.getDisplayContent());
- assertNull(task.mStack);
+ assertNull(task.getTaskStack());
}
@Test
@@ -141,7 +142,7 @@
final Task task = createTaskInStack(stack, 0 /* userId */);
// Stack removal is deferred if one of its child is animating.
- doReturn(true).when(task).isSelfAnimating();
+ doReturn(true).when(task).isAnimating(TRANSITION | CHILDREN);
stack.removeIfPossible();
// For the case of deferred removal the task controller will still be connected to the its
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 4dfa2664..cb2e1e0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -92,7 +94,7 @@
boolean gotException = false;
try {
- task.reparent(stackController1, 0, false/* moveParents */);
+ task.reparent(stackController1, 0, false/* moveParents */, "testReparent");
} catch (IllegalArgumentException e) {
gotException = true;
}
@@ -100,14 +102,14 @@
gotException = false;
try {
- task.reparent(null, 0, false/* moveParents */);
+ task.reparent(null, 0, false/* moveParents */, "testReparent");
} catch (IllegalArgumentException e) {
gotException = true;
}
assertTrue("Should not be able to reparent to a stack that doesn't exist",
gotException);
- task.reparent(stackController2, 0, false/* moveParents */);
+ task.reparent(stackController2, 0, false/* moveParents */, "testReparent");
assertEquals(stackController2, task.getParent());
assertEquals(0, task.getParent().mChildren.indexOf(task));
assertEquals(1, task2.getParent().mChildren.indexOf(task2));
@@ -125,7 +127,7 @@
final TaskStack stack2 = createTaskStackOnDisplay(dc);
final Task task2 = createTaskInStack(stack2, 0 /* userId */);
// Reparent and check state
- task.reparent(stack2, 0, false /* moveParents */);
+ task.reparent(stack2, 0, false /* moveParents */, "testReparent_BetweenDisplays");
assertEquals(stack2, task.getParent());
assertEquals(0, task.getParent().mChildren.indexOf(task));
assertEquals(1, task2.getParent().mChildren.indexOf(task2));
@@ -138,6 +140,7 @@
final Task task = createTaskInStack(stack1, 0 /* userId */);
// Check that setting bounds also updates surface position
+ task.setWindowingMode(WINDOWING_MODE_FREEFORM);
Rect bounds = new Rect(10, 10, 100, 200);
task.setBounds(bounds);
assertEquals(new Point(bounds.left, bounds.top), task.getLastSurfacePosition());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
index d6608f1..64ac547 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowConfigurationTests.java
@@ -20,13 +20,17 @@
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOW_CONFIG_ALWAYS_ON_TOP;
import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS;
+import static android.app.WindowConfiguration.WINDOW_CONFIG_BOUNDS;
import static android.app.WindowConfiguration.WINDOW_CONFIG_ROTATION;
import static android.app.WindowConfiguration.WINDOW_CONFIG_WINDOWING_MODE;
import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
+import static android.view.Surface.ROTATION_270;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -218,4 +222,31 @@
config.setActivityType(ACTIVITY_TYPE_STANDARD);
assertTrue(config.hasWindowDecorCaption());
}
+
+ @Test
+ public void testMaskedSetTo() {
+ final WindowConfiguration config = new WindowConfiguration();
+ final WindowConfiguration other = new WindowConfiguration();
+ other.setBounds(new Rect(10, 10, 100, 100));
+ other.setRotation(ROTATION_270);
+ config.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ config.setBounds(null);
+
+ // no change
+ config.setTo(other, 0);
+ assertTrue(config.getBounds().isEmpty());
+ assertEquals(ROTATION_UNDEFINED, config.getRotation());
+ assertEquals(WINDOWING_MODE_FULLSCREEN, config.getWindowingMode());
+
+ final int justBoundsAndRotation = WINDOW_CONFIG_BOUNDS | WINDOW_CONFIG_ROTATION;
+ config.setTo(other, justBoundsAndRotation);
+ assertEquals(other.getBounds(), config.getBounds());
+ assertEquals(other.getRotation(), config.getRotation());
+ assertEquals(WINDOWING_MODE_FULLSCREEN, config.getWindowingMode());
+
+ // unsets as well
+ final int justWindowingMode = WINDOW_CONFIG_WINDOWING_MODE;
+ config.setTo(other, justWindowingMode);
+ assertEquals(WINDOWING_MODE_UNDEFINED, config.getWindowingMode());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index 85aff7f..8536448 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -24,13 +24,18 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyFloat;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
+import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
+import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
@@ -335,7 +340,53 @@
}
@Test
- public void testIsAnimating() {
+ public void testIsAnimating_TransitionFlag() {
+ final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
+ final TestWindowContainer root = builder.setLayer(0).build();
+ final TestWindowContainer child1 = root.addChildWindow(
+ builder.setWaitForTransitionStart(true));
+
+ assertFalse(root.isAnimating(TRANSITION));
+ assertTrue(child1.isAnimating(TRANSITION));
+ }
+
+ @Test
+ public void testIsAnimating_ParentsFlag() {
+ final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
+ final TestWindowContainer root = builder.setLayer(0).build();
+ final TestWindowContainer child1 = root.addChildWindow(builder);
+ final TestWindowContainer child2 = root.addChildWindow(builder.setIsAnimating(true));
+ final TestWindowContainer child21 = child2.addChildWindow(builder.setIsAnimating(false));
+
+ assertFalse(root.isAnimating());
+ assertFalse(child1.isAnimating());
+ assertFalse(child1.isAnimating(PARENTS));
+ assertTrue(child2.isAnimating());
+ assertTrue(child2.isAnimating(PARENTS));
+ assertFalse(child21.isAnimating());
+ assertTrue(child21.isAnimating(PARENTS));
+ }
+
+ @Test
+ public void testIsAnimating_ChildrenFlag() {
+ final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
+ final TestWindowContainer root = builder.setLayer(0).build();
+ final TestWindowContainer child1 = root.addChildWindow(builder);
+ final TestWindowContainer child2 = root.addChildWindow(builder.setIsAnimating(true));
+ final TestWindowContainer child11 = child1.addChildWindow(builder.setIsAnimating(true));
+
+ assertFalse(root.isAnimating());
+ assertTrue(root.isAnimating(CHILDREN));
+ assertFalse(child1.isAnimating());
+ assertTrue(child1.isAnimating(CHILDREN));
+ assertTrue(child2.isAnimating());
+ assertTrue(child2.isAnimating(CHILDREN));
+ assertTrue(child11.isAnimating());
+ assertTrue(child11.isAnimating(CHILDREN));
+ }
+
+ @Test
+ public void testIsAnimating_combineFlags() {
final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
final TestWindowContainer root = builder.setLayer(0).build();
@@ -345,19 +396,19 @@
final TestWindowContainer child12 = child1.addChildWindow(builder.setIsAnimating(true));
final TestWindowContainer child21 = child2.addChildWindow();
- assertFalse(root.isAnimating());
- assertTrue(child1.isAnimating());
- assertTrue(child11.isAnimating());
- assertTrue(child12.isAnimating());
- assertFalse(child2.isAnimating());
- assertFalse(child21.isAnimating());
+ assertFalse(root.isAnimating(TRANSITION | PARENTS));
+ assertTrue(child1.isAnimating(TRANSITION | PARENTS));
+ assertTrue(child11.isAnimating(TRANSITION | PARENTS));
+ assertTrue(child12.isAnimating(TRANSITION | PARENTS));
+ assertFalse(child2.isAnimating(TRANSITION | PARENTS));
+ assertFalse(child21.isAnimating(TRANSITION | PARENTS));
- assertTrue(root.isSelfOrChildAnimating());
- assertTrue(child1.isSelfOrChildAnimating());
- assertFalse(child11.isSelfOrChildAnimating());
- assertTrue(child12.isSelfOrChildAnimating());
- assertFalse(child2.isSelfOrChildAnimating());
- assertFalse(child21.isSelfOrChildAnimating());
+ assertTrue(root.isAnimating(TRANSITION | CHILDREN));
+ assertTrue(child1.isAnimating(TRANSITION | CHILDREN));
+ assertFalse(child11.isAnimating(TRANSITION | CHILDREN));
+ assertTrue(child12.isAnimating(TRANSITION | CHILDREN));
+ assertFalse(child2.isAnimating(TRANSITION | CHILDREN));
+ assertFalse(child21.isAnimating(TRANSITION | CHILDREN));
}
@Test
@@ -716,6 +767,7 @@
private boolean mIsAnimating;
private boolean mIsVisible;
private boolean mFillsParent;
+ private boolean mWaitForTransitStart;
private Integer mOrientation;
private boolean mOnParentChangedCalled;
@@ -738,7 +790,7 @@
};
TestWindowContainer(WindowManagerService wm, int layer, boolean isAnimating,
- boolean isVisible, Integer orientation) {
+ boolean isVisible, boolean waitTransitStart, Integer orientation) {
super(wm);
mLayer = layer;
@@ -746,6 +798,9 @@
mIsVisible = isVisible;
mFillsParent = true;
mOrientation = orientation;
+ mWaitForTransitStart = waitTransitStart;
+ spyOn(mSurfaceAnimator);
+ doReturn(mIsAnimating).when(mSurfaceAnimator).isAnimating();
}
TestWindowContainer getParentWindow() {
@@ -783,11 +838,6 @@
}
@Override
- boolean isSelfAnimating() {
- return mIsAnimating;
- }
-
- @Override
boolean isVisible() {
return mIsVisible;
}
@@ -810,6 +860,11 @@
void setFillsParent(boolean fillsParent) {
mFillsParent = fillsParent;
}
+
+ @Override
+ boolean isWaitingForTransitionStart() {
+ return mWaitForTransitStart;
+ }
}
private static class TestWindowContainerBuilder {
@@ -817,6 +872,7 @@
private int mLayer;
private boolean mIsAnimating;
private boolean mIsVisible;
+ private boolean mIsWaitTransitStart;
private Integer mOrientation;
TestWindowContainerBuilder(WindowManagerService wm) {
@@ -847,8 +903,14 @@
return this;
}
+ TestWindowContainerBuilder setWaitForTransitionStart(boolean waitTransitStart) {
+ mIsWaitTransitStart = waitTransitStart;
+ return this;
+ }
+
TestWindowContainer build() {
- return new TestWindowContainer(mWm, mLayer, mIsAnimating, mIsVisible, mOrientation);
+ return new TestWindowContainer(mWm, mLayer, mIsAnimating, mIsVisible,
+ mIsWaitTransitStart, mOrientation);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java
similarity index 86%
rename from services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java
rename to services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java
index 8520d21..b8de3ca 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowThumbnailTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java
@@ -37,27 +37,27 @@
* Test class for {@link TaskSnapshotSurface}.
*
* Build/Install/Run:
- * atest FrameworksServicesTest:AppWindowThumbnailTest
+ * atest WmTests:WindowContainerThumbnailTest
*
*/
@SmallTest
@Presubmit
@RunWith(WindowTestRunner.class)
-public class AppWindowThumbnailTest extends WindowTestsBase {
- private AppWindowThumbnail buildThumbnail() {
+public class WindowContainerThumbnailTest extends WindowTestsBase {
+ private WindowContainerThumbnail buildThumbnail() {
final GraphicBuffer buffer = GraphicBuffer.create(1, 1, PixelFormat.RGBA_8888,
GraphicBuffer.USAGE_SW_READ_RARELY | GraphicBuffer.USAGE_SW_WRITE_NEVER);
final ActivityRecord mockAr = mock(ActivityRecord.class);
when(mockAr.getPendingTransaction()).thenReturn(new StubTransaction());
when(mockAr.makeSurface()).thenReturn(new MockSurfaceControlBuilder());
- return new AppWindowThumbnail(new StubTransaction(), mockAr,
+ return new WindowContainerThumbnail(new StubTransaction(), mockAr,
buffer, false, mock(Surface.class), mock(SurfaceAnimator.class));
}
@Test
@FlakyTest(bugId = 131005232)
public void testDestroy_nullsSurface() {
- final AppWindowThumbnail t = buildThumbnail();
+ final WindowContainerThumbnail t = buildThumbnail();
assertNotNull(t.getSurfaceControl());
t.destroy();
assertNull(t.getSurfaceControl());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
index 8cd97cb..428d869 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowFrameTests.java
@@ -255,6 +255,7 @@
@Test
public void testLayoutNonfullscreenTask() {
+ removeGlobalMinSizeRestriction();
final DisplayInfo displayInfo = mWm.getDefaultDisplayContentLocked().getDisplayInfo();
final int logicalWidth = displayInfo.logicalWidth;
final int logicalHeight = displayInfo.logicalHeight;
@@ -264,8 +265,8 @@
WindowState w = createWindow();
final Task task = w.getTask();
// Use split-screen because it is non-fullscreen, but also not floating
- task.mTaskRecord.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
- task.mTaskRecord.setBounds(taskBounds);
+ task.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+ task.setBounds(taskBounds);
// The bounds we are requesting might be different from what the system resolved based on
// other factors.
final Rect resolvedTaskBounds = task.getBounds();
@@ -303,8 +304,8 @@
final int insetTop = logicalHeight / 5;
final int insetRight = insetLeft + (resolvedTaskBounds.right - resolvedTaskBounds.left);
final int insetBottom = insetTop + (resolvedTaskBounds.bottom - resolvedTaskBounds.top);
- task.mTaskRecord.setDisplayedBounds(resolvedTaskBounds);
- task.mTaskRecord.setBounds(insetLeft, insetTop, insetRight, insetBottom);
+ task.setOverrideDisplayedBounds(resolvedTaskBounds);
+ task.setBounds(insetLeft, insetTop, insetRight, insetBottom);
windowFrames.setFrames(pf, pf, pf, cf, cf, pf, cf, mEmptyRect);
w.computeFrameLw();
assertEquals(resolvedTaskBounds, w.getFrameLw());
@@ -477,7 +478,7 @@
WindowState w = createWindow();
final Task task = w.getTask();
w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
- task.mTaskRecord.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ task.setWindowingMode(WINDOWING_MODE_FREEFORM);
DisplayContent dc = mTestDisplayContent;
dc.mInputMethodTarget = w;
@@ -499,7 +500,7 @@
// First check that it only gets moved up enough to show window.
final Rect winRect = new Rect(200, 200, 300, 500);
- task.mTaskRecord.setBounds(winRect);
+ task.setBounds(winRect);
w.getWindowFrames().setFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
w.computeFrameLw();
@@ -511,7 +512,7 @@
// Now check that it won't get moved beyond the top and then has appropriate insets
winRect.bottom = 600;
- task.mTaskRecord.setBounds(winRect);
+ task.setBounds(winRect);
w.setBounds(winRect);
w.getWindowFrames().setFrames(pf, df, of, cf, vf, dcf, sf, mEmptyRect);
w.computeFrameLw();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index 51daf65..3f32e33 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -42,7 +42,7 @@
.setUserId(userId)
.setStack(stack.mActivityStack)
.build();
- return task.mTask;
+ return task;
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 780fed9..c3f59eb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -384,7 +384,7 @@
}
/** Sets the default minimum task size to 1 so that tests can use small task sizes */
- public void removeGlobalMinSizeRestriction() {
+ void removeGlobalMinSizeRestriction() {
mWm.mAtmService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp = 1;
}
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java b/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
index 7d8e430..b68e04f 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java
@@ -448,10 +448,10 @@
final long packagesToken = proto.start(
IntervalStatsObfuscatedProto.PACKAGES);
UsageStats usageStats = parseUsageStats(proto, stats.beginTime);
+ proto.end(packagesToken);
if (usageStats.mPackageToken != PackagesTokenData.UNASSIGNED_TOKEN) {
stats.packageStatsObfuscated.put(usageStats.mPackageToken, usageStats);
}
- proto.end(packagesToken);
} catch (IOException e) {
Slog.e(TAG, "Unable to read some usage stats from proto.", e);
}
@@ -484,6 +484,13 @@
if (stats.endTime == 0) {
stats.endTime = stats.beginTime;
}
+ // update the begin and end time stamps for all usage stats
+ final int usageStatsSize = stats.packageStatsObfuscated.size();
+ for (int i = 0; i < usageStatsSize; i++) {
+ final UsageStats usageStats = stats.packageStatsObfuscated.valueAt(i);
+ usageStats.mBeginTimeStamp = stats.beginTime;
+ usageStats.mEndTimeStamp = stats.endTime;
+ }
return;
}
}
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 6a80568..f9b3659 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -400,7 +400,7 @@
private final IUidObserver mUidObserver = new IUidObserver.Stub() {
@Override
- public void onUidStateChanged(int uid, int procState, long procStateSeq) {
+ public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) {
mHandler.obtainMessage(MSG_UID_STATE_CHANGED, uid, procState).sendToTarget();
}
@@ -411,7 +411,8 @@
@Override
public void onUidGone(int uid, boolean disabled) {
- onUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT, 0);
+ onUidStateChanged(uid, ActivityManager.PROCESS_STATE_NONEXISTENT, 0,
+ ActivityManager.PROCESS_CAPABILITY_NONE);
}
@Override
diff --git a/startop/view_compiler/Android.bp b/startop/view_compiler/Android.bp
index c380d29..7cc233b 100644
--- a/startop/view_compiler/Android.bp
+++ b/startop/view_compiler/Android.bp
@@ -16,7 +16,6 @@
cc_defaults {
name: "viewcompiler_defaults",
- defaults: ["libdexfile_static_defaults"],
header_libs: [
"libbase_headers",
],
@@ -30,6 +29,7 @@
"liblog",
"libutils",
"libziparchive",
+ "libz",
],
cppflags: ["-std=c++17"],
target: {
diff --git a/startop/view_compiler/dex_builder.cc b/startop/view_compiler/dex_builder.cc
index 48b44d0..50cf5a5 100644
--- a/startop/view_compiler/dex_builder.cc
+++ b/startop/view_compiler/dex_builder.cc
@@ -16,8 +16,6 @@
#include "dex_builder.h"
-#include "dex/descriptors_names.h"
-
#include <fstream>
#include <memory>
@@ -30,8 +28,6 @@
using ::dex::kAccPublic;
using Op = Instruction::Op;
-using Opcode = ::art::Instruction::Code;
-
const TypeDescriptor TypeDescriptor::Int() { return TypeDescriptor{"I"}; };
const TypeDescriptor TypeDescriptor::Void() { return TypeDescriptor{"V"}; };
@@ -43,22 +39,31 @@
constexpr size_t kMaxEncodedStringLength{5};
// Converts invoke-* to invoke-*/range
-constexpr Opcode InvokeToInvokeRange(Opcode opcode) {
+constexpr ::dex::Opcode InvokeToInvokeRange(::dex::Opcode opcode) {
switch (opcode) {
- case ::art::Instruction::INVOKE_VIRTUAL:
- return ::art::Instruction::INVOKE_VIRTUAL_RANGE;
- case ::art::Instruction::INVOKE_DIRECT:
- return ::art::Instruction::INVOKE_DIRECT_RANGE;
- case ::art::Instruction::INVOKE_STATIC:
- return ::art::Instruction::INVOKE_STATIC_RANGE;
- case ::art::Instruction::INVOKE_INTERFACE:
- return ::art::Instruction::INVOKE_INTERFACE_RANGE;
+ case ::dex::Opcode::OP_INVOKE_VIRTUAL:
+ return ::dex::Opcode::OP_INVOKE_VIRTUAL_RANGE;
+ case ::dex::Opcode::OP_INVOKE_DIRECT:
+ return ::dex::Opcode::OP_INVOKE_DIRECT_RANGE;
+ case ::dex::Opcode::OP_INVOKE_STATIC:
+ return ::dex::Opcode::OP_INVOKE_STATIC_RANGE;
+ case ::dex::Opcode::OP_INVOKE_INTERFACE:
+ return ::dex::Opcode::OP_INVOKE_INTERFACE_RANGE;
default:
LOG(FATAL) << opcode << " is not a recognized invoke opcode.";
- UNREACHABLE();
+ __builtin_unreachable();
}
}
+std::string DotToDescriptor(const char* class_name) {
+ std::string descriptor(class_name);
+ std::replace(descriptor.begin(), descriptor.end(), '.', '/');
+ if (descriptor.length() > 0 && descriptor[0] != '[') {
+ descriptor = "L" + descriptor + ";";
+ }
+ return descriptor;
+}
+
} // namespace
std::ostream& operator<<(std::ostream& out, const Instruction::Op& opcode) {
@@ -178,7 +183,7 @@
}
TypeDescriptor TypeDescriptor::FromClassname(const std::string& name) {
- return TypeDescriptor{art::DotToDescriptor(name.c_str())};
+ return TypeDescriptor{DotToDescriptor(name.c_str())};
}
DexBuilder::DexBuilder() : dex_file_{std::make_shared<ir::DexFile>()} {
@@ -219,11 +224,11 @@
ClassBuilder DexBuilder::MakeClass(const std::string& name) {
auto* class_def = Alloc<ir::Class>();
- ir::Type* type_def = GetOrAddType(art::DotToDescriptor(name.c_str()));
+ ir::Type* type_def = GetOrAddType(DotToDescriptor(name.c_str()));
type_def->class_def = class_def;
class_def->type = type_def;
- class_def->super_class = GetOrAddType(art::DotToDescriptor("java.lang.Object"));
+ class_def->super_class = GetOrAddType(DotToDescriptor("java.lang.Object"));
class_def->access_flags = kAccPublic;
return ClassBuilder{this, name, class_def};
}
@@ -378,26 +383,26 @@
void MethodBuilder::EncodeInstruction(const Instruction& instruction) {
switch (instruction.opcode()) {
case Instruction::Op::kReturn:
- return EncodeReturn(instruction, ::art::Instruction::RETURN);
+ return EncodeReturn(instruction, ::dex::Opcode::OP_RETURN);
case Instruction::Op::kReturnObject:
- return EncodeReturn(instruction, ::art::Instruction::RETURN_OBJECT);
+ return EncodeReturn(instruction, ::dex::Opcode::OP_RETURN_OBJECT);
case Instruction::Op::kMove:
case Instruction::Op::kMoveObject:
return EncodeMove(instruction);
case Instruction::Op::kInvokeVirtual:
- return EncodeInvoke(instruction, art::Instruction::INVOKE_VIRTUAL);
+ return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_VIRTUAL);
case Instruction::Op::kInvokeDirect:
- return EncodeInvoke(instruction, art::Instruction::INVOKE_DIRECT);
+ return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_DIRECT);
case Instruction::Op::kInvokeStatic:
- return EncodeInvoke(instruction, art::Instruction::INVOKE_STATIC);
+ return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_STATIC);
case Instruction::Op::kInvokeInterface:
- return EncodeInvoke(instruction, art::Instruction::INVOKE_INTERFACE);
+ return EncodeInvoke(instruction, ::dex::Opcode::OP_INVOKE_INTERFACE);
case Instruction::Op::kBindLabel:
return BindLabel(instruction.args()[0]);
case Instruction::Op::kBranchEqz:
- return EncodeBranch(art::Instruction::IF_EQZ, instruction);
+ return EncodeBranch(::dex::Opcode::OP_IF_EQZ, instruction);
case Instruction::Op::kBranchNEqz:
- return EncodeBranch(art::Instruction::IF_NEZ, instruction);
+ return EncodeBranch(::dex::Opcode::OP_IF_NEZ, instruction);
case Instruction::Op::kNew:
return EncodeNew(instruction);
case Instruction::Op::kCheckCast:
@@ -410,10 +415,10 @@
}
}
-void MethodBuilder::EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode) {
+void MethodBuilder::EncodeReturn(const Instruction& instruction, ::dex::Opcode opcode) {
CHECK(!instruction.dest().has_value());
if (instruction.args().size() == 0) {
- Encode10x(art::Instruction::RETURN_VOID);
+ Encode10x(::dex::Opcode::OP_RETURN_VOID);
} else {
CHECK_EQ(1, instruction.args().size());
size_t source = RegisterValue(instruction.args()[0]);
@@ -433,27 +438,27 @@
if (source.is_immediate()) {
// TODO: support more registers
CHECK_LT(RegisterValue(*instruction.dest()), 16);
- Encode11n(art::Instruction::CONST_4, RegisterValue(*instruction.dest()), source.value());
+ Encode11n(::dex::Opcode::OP_CONST_4, RegisterValue(*instruction.dest()), source.value());
} else if (source.is_string()) {
constexpr size_t kMaxRegisters = 256;
CHECK_LT(RegisterValue(*instruction.dest()), kMaxRegisters);
CHECK_LT(source.value(), 65536); // make sure we don't need a jumbo string
- Encode21c(::art::Instruction::CONST_STRING, RegisterValue(*instruction.dest()), source.value());
+ Encode21c(::dex::Opcode::OP_CONST_STRING, RegisterValue(*instruction.dest()), source.value());
} else if (source.is_variable()) {
// For the moment, we only use this when we need to reshuffle registers for
// an invoke instruction, meaning we are too big for the 4-bit version.
// We'll err on the side of caution and always generate the 16-bit form of
// the instruction.
- Opcode opcode = instruction.opcode() == Instruction::Op::kMove
- ? ::art::Instruction::MOVE_16
- : ::art::Instruction::MOVE_OBJECT_16;
+ auto opcode = instruction.opcode() == Instruction::Op::kMove
+ ? ::dex::Opcode::OP_MOVE_16
+ : ::dex::Opcode::OP_MOVE_OBJECT_16;
Encode32x(opcode, RegisterValue(*instruction.dest()), RegisterValue(source));
} else {
UNIMPLEMENTED(FATAL);
}
}
-void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode) {
+void MethodBuilder::EncodeInvoke(const Instruction& instruction, ::dex::Opcode opcode) {
constexpr size_t kMaxArgs = 5;
// Currently, we only support up to 5 arguments.
@@ -480,8 +485,8 @@
for (size_t i = 0; i < instruction.args().size(); ++i) {
Instruction::Op move_op;
- if (opcode == ::art::Instruction::INVOKE_VIRTUAL ||
- opcode == ::art::Instruction::INVOKE_DIRECT) {
+ if (opcode == ::dex::Opcode::OP_INVOKE_VIRTUAL ||
+ opcode == ::dex::Opcode::OP_INVOKE_DIRECT) {
// In this case, there is an implicit `this` argument, which is always an object.
if (i == 0) {
move_op = Instruction::Op::kMoveObject;
@@ -514,8 +519,8 @@
// If there is a return value, add a move-result instruction
if (instruction.dest().has_value()) {
- Encode11x(instruction.result_is_object() ? art::Instruction::MOVE_RESULT_OBJECT
- : art::Instruction::MOVE_RESULT,
+ Encode11x(instruction.result_is_object() ? ::dex::Opcode::OP_MOVE_RESULT_OBJECT
+ : ::dex::Opcode::OP_MOVE_RESULT,
RegisterValue(*instruction.dest()));
}
@@ -523,7 +528,7 @@
}
// Encodes a conditional branch that tests a single argument.
-void MethodBuilder::EncodeBranch(art::Instruction::Code op, const Instruction& instruction) {
+void MethodBuilder::EncodeBranch(::dex::Opcode op, const Instruction& instruction) {
const auto& args = instruction.args();
const auto& test_value = args[0];
const auto& branch_target = args[1];
@@ -546,7 +551,7 @@
const Value& type = instruction.args()[0];
CHECK_LT(RegisterValue(*instruction.dest()), 256);
CHECK(type.is_type());
- Encode21c(::art::Instruction::NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value());
+ Encode21c(::dex::Opcode::OP_NEW_INSTANCE, RegisterValue(*instruction.dest()), type.value());
}
void MethodBuilder::EncodeCast(const Instruction& instruction) {
@@ -558,7 +563,7 @@
const Value& type = instruction.args()[0];
CHECK_LT(RegisterValue(*instruction.dest()), 256);
CHECK(type.is_type());
- Encode21c(::art::Instruction::CHECK_CAST, RegisterValue(*instruction.dest()), type.value());
+ Encode21c(::dex::Opcode::OP_CHECK_CAST, RegisterValue(*instruction.dest()), type.value());
}
void MethodBuilder::EncodeFieldOp(const Instruction& instruction) {
@@ -569,7 +574,7 @@
CHECK(instruction.dest()->is_variable());
CHECK_EQ(0, instruction.args().size());
- Encode21c(::art::Instruction::SGET,
+ Encode21c(::dex::Opcode::OP_SGET,
RegisterValue(*instruction.dest()),
instruction.index_argument());
break;
@@ -579,7 +584,7 @@
CHECK_EQ(1, args.size());
CHECK(args[0].is_variable());
- Encode21c(::art::Instruction::SPUT, RegisterValue(args[0]), instruction.index_argument());
+ Encode21c(::dex::Opcode::OP_SPUT, RegisterValue(args[0]), instruction.index_argument());
break;
}
case Instruction::Op::kGetInstanceField: {
@@ -587,7 +592,7 @@
CHECK(instruction.dest()->is_variable());
CHECK_EQ(1, instruction.args().size());
- Encode22c(::art::Instruction::IGET,
+ Encode22c(::dex::Opcode::OP_IGET,
RegisterValue(*instruction.dest()),
RegisterValue(args[0]),
instruction.index_argument());
@@ -599,7 +604,7 @@
CHECK(args[0].is_variable());
CHECK(args[1].is_variable());
- Encode22c(::art::Instruction::IPUT,
+ Encode22c(::dex::Opcode::OP_IPUT,
RegisterValue(args[1]),
RegisterValue(args[0]),
instruction.index_argument());
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
index 3924e77..eb2dc88 100644
--- a/startop/view_compiler/dex_builder.h
+++ b/startop/view_compiler/dex_builder.h
@@ -24,7 +24,9 @@
#include <unordered_map>
#include <vector>
-#include "dex/dex_instruction.h"
+#include "android-base/logging.h"
+
+#include "slicer/dex_bytecode.h"
#include "slicer/dex_ir.h"
#include "slicer/writer.h"
@@ -364,11 +366,11 @@
// Encodes a return instruction. For instructions with no return value, the opcode field is
// ignored. Otherwise, this specifies which return instruction will be used (return,
// return-object, etc.)
- void EncodeReturn(const Instruction& instruction, ::art::Instruction::Code opcode);
+ void EncodeReturn(const Instruction& instruction, ::dex::Opcode opcode);
void EncodeMove(const Instruction& instruction);
- void EncodeInvoke(const Instruction& instruction, ::art::Instruction::Code opcode);
- void EncodeBranch(art::Instruction::Code op, const Instruction& instruction);
+ void EncodeInvoke(const Instruction& instruction, ::dex::Opcode opcode);
+ void EncodeBranch(::dex::Opcode op, const Instruction& instruction);
void EncodeNew(const Instruction& instruction);
void EncodeCast(const Instruction& instruction);
void EncodeFieldOp(const Instruction& instruction);
@@ -377,17 +379,23 @@
// https://source.android.com/devices/tech/dalvik/instruction-formats for documentation of
// formats.
- inline void Encode10x(art::Instruction::Code opcode) {
+ inline uint8_t ToBits(::dex::Opcode opcode) {
+ static_assert(sizeof(uint8_t) == sizeof(::dex::Opcode));
+ return static_cast<uint8_t>(opcode);
+ }
+
+ inline void Encode10x(::dex::Opcode opcode) {
// 00|op
- buffer_.push_back(opcode);
+ static_assert(sizeof(uint8_t) == sizeof(::dex::Opcode));
+ buffer_.push_back(ToBits(opcode));
}
- inline void Encode11x(art::Instruction::Code opcode, uint8_t a) {
+ inline void Encode11x(::dex::Opcode opcode, uint8_t a) {
// aa|op
- buffer_.push_back((a << 8) | opcode);
+ buffer_.push_back((a << 8) | ToBits(opcode));
}
- inline void Encode11n(art::Instruction::Code opcode, uint8_t a, int8_t b) {
+ inline void Encode11n(::dex::Opcode opcode, uint8_t a, int8_t b) {
// b|a|op
// Make sure the fields are in bounds (4 bits for a, 4 bits for b).
@@ -395,30 +403,30 @@
CHECK_LE(-8, b);
CHECK_LT(b, 8);
- buffer_.push_back(((b & 0xf) << 12) | (a << 8) | opcode);
+ buffer_.push_back(((b & 0xf) << 12) | (a << 8) | ToBits(opcode));
}
- inline void Encode21c(art::Instruction::Code opcode, uint8_t a, uint16_t b) {
+ inline void Encode21c(::dex::Opcode opcode, uint8_t a, uint16_t b) {
// aa|op|bbbb
- buffer_.push_back((a << 8) | opcode);
+ buffer_.push_back((a << 8) | ToBits(opcode));
buffer_.push_back(b);
}
- inline void Encode22c(art::Instruction::Code opcode, uint8_t a, uint8_t b, uint16_t c) {
+ inline void Encode22c(::dex::Opcode opcode, uint8_t a, uint8_t b, uint16_t c) {
// b|a|op|bbbb
CHECK(IsShortRegister(a));
CHECK(IsShortRegister(b));
- buffer_.push_back((b << 12) | (a << 8) | opcode);
+ buffer_.push_back((b << 12) | (a << 8) | ToBits(opcode));
buffer_.push_back(c);
}
- inline void Encode32x(art::Instruction::Code opcode, uint16_t a, uint16_t b) {
- buffer_.push_back(opcode);
+ inline void Encode32x(::dex::Opcode opcode, uint16_t a, uint16_t b) {
+ buffer_.push_back(ToBits(opcode));
buffer_.push_back(a);
buffer_.push_back(b);
}
- inline void Encode35c(art::Instruction::Code opcode, size_t a, uint16_t b, uint8_t c, uint8_t d,
+ inline void Encode35c(::dex::Opcode opcode, size_t a, uint16_t b, uint8_t c, uint8_t d,
uint8_t e, uint8_t f, uint8_t g) {
// a|g|op|bbbb|f|e|d|c
@@ -428,14 +436,14 @@
CHECK(IsShortRegister(e));
CHECK(IsShortRegister(f));
CHECK(IsShortRegister(g));
- buffer_.push_back((a << 12) | (g << 8) | opcode);
+ buffer_.push_back((a << 12) | (g << 8) | ToBits(opcode));
buffer_.push_back(b);
buffer_.push_back((f << 12) | (e << 8) | (d << 4) | c);
}
- inline void Encode3rc(art::Instruction::Code opcode, size_t a, uint16_t b, uint16_t c) {
+ inline void Encode3rc(::dex::Opcode opcode, size_t a, uint16_t b, uint16_t c) {
CHECK_LE(a, 255);
- buffer_.push_back((a << 8) | opcode);
+ buffer_.push_back((a << 8) | ToBits(opcode));
buffer_.push_back(b);
buffer_.push_back(c);
}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index fa16b84..20abe77 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -858,7 +858,7 @@
}
/** @hide */
- public abstract static class Listener {
+ abstract static class Listener {
public void onStateChanged(Connection c, int state) {}
public void onAddressChanged(Connection c, Uri newAddress, int presentation) {}
public void onCallerDisplayNameChanged(
@@ -2006,7 +2006,7 @@
*
* @hide
*/
- public final Connection addConnectionListener(Listener l) {
+ final Connection addConnectionListener(Listener l) {
mListeners.add(l);
return this;
}
@@ -2019,7 +2019,7 @@
*
* @hide
*/
- public final Connection removeConnectionListener(Listener l) {
+ final Connection removeConnectionListener(Listener l) {
if (l != null) {
mListeners.remove(l);
}
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index bc29b59..dc95f16 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -16,6 +16,7 @@
package android.provider;
+import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
@@ -3943,10 +3944,11 @@
}
/**
- * Contains received SMS cell broadcast messages. More details are available in 3GPP TS 23.041.
+ * Contains received cell broadcast messages. More details are available in 3GPP TS 23.041.
* @hide
*/
@SystemApi
+ @TestApi
public static final class CellBroadcasts implements BaseColumns {
/**
@@ -3957,11 +3959,44 @@
/**
* The {@code content://} URI for this table.
+ * Only privileged framework components running on phone or network stack uid can
+ * query or modify this table.
*/
@NonNull
public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts");
/**
+ * The {@code content://} URI for query cellbroadcast message history.
+ * query results include following entries
+ * <ul>
+ * <li>{@link #_ID}</li>
+ * <li>{@link #SLOT_INDEX}</li>
+ * <li>{@link #GEOGRAPHICAL_SCOPE}</li>
+ * <li>{@link #PLMN}</li>
+ * <li>{@link #LAC}</li>
+ * <li>{@link #CID}</li>
+ * <li>{@link #SERIAL_NUMBER}</li>
+ * <li>{@link #SERVICE_CATEGORY}</li>
+ * <li>{@link #LANGUAGE_CODE}</li>
+ * <li>{@link #MESSAGE_BODY}</li>
+ * <li>{@link #DELIVERY_TIME}</li>
+ * <li>{@link #MESSAGE_READ}</li>
+ * <li>{@link #MESSAGE_FORMAT}</li>
+ * <li>{@link #MESSAGE_PRIORITY}</li>
+ * <li>{@link #ETWS_WARNING_TYPE}</li>
+ * <li>{@link #CMAS_MESSAGE_CLASS}</li>
+ * <li>{@link #CMAS_CATEGORY}</li>
+ * <li>{@link #CMAS_RESPONSE_TYPE}</li>
+ * <li>{@link #CMAS_SEVERITY}</li>
+ * <li>{@link #CMAS_URGENCY}</li>
+ * <li>{@link #CMAS_CERTAINTY}</li>
+ * </ul>
+ */
+ @RequiresPermission(Manifest.permission.READ_CELL_BROADCASTS)
+ @NonNull
+ public static final Uri MESSAGE_HISTORY_URI = Uri.parse("content://cellbroadcasts/history");
+
+ /**
* The subscription which received this cell broadcast message.
* @deprecated use {@link #SLOT_INDEX} instead.
* <P>Type: INTEGER</P>
@@ -3972,7 +4007,6 @@
/**
* The slot which received this cell broadcast message.
* <P>Type: INTEGER</P>
- * @hide
*/
public static final String SLOT_INDEX = "slot_index";
@@ -4150,14 +4184,12 @@
/**
* The timestamp in millisecond of when the device received the message.
* <P>Type: BIGINT</P>
- * @hide
*/
public static final String RECEIVED_TIME = "received_time";
/**
* Indicates that whether the message has been broadcasted to the application.
* <P>Type: BOOLEAN</P>
- * @hide
*/
public static final String MESSAGE_BROADCASTED = "message_broadcasted";
@@ -4193,7 +4225,6 @@
* "circle|0,0|100;polygon|0,0|0,1.5|1,1|1,0;circle|100.123,100|200.123"
*
* <P>Type: TEXT</P>
- * @hide
*/
public static final String GEOMETRIES = "geometries";
@@ -4205,7 +4236,6 @@
* for the alert.
*
* <P>Type: INTEGER</P>
- * @hide
*/
public static final String MAXIMUM_WAIT_TIME = "maximum_wait_time";
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index afa35b4..a0aa60b 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -45,6 +45,7 @@
* @hide
*/
@SystemApi
+ @TestApi
public static final int TRANSPORT_TYPE_INVALID = -1;
/**
diff --git a/telephony/java/android/telephony/CallQuality.java b/telephony/java/android/telephony/CallQuality.java
index 028280c..e01deb2 100644
--- a/telephony/java/android/telephony/CallQuality.java
+++ b/telephony/java/android/telephony/CallQuality.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -40,6 +41,7 @@
* @hide
*/
@SystemApi
+@TestApi
public final class CallQuality implements Parcelable {
// Constants representing the call quality level (see #CallQuality);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
old mode 100644
new mode 100755
index 58e15b9..1e24558
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -828,13 +828,6 @@
"disable_severe_when_extreme_disabled_bool";
/**
- * The message expiration time in milliseconds for duplicate detection purposes.
- * @hide
- */
- public static final String KEY_MESSAGE_EXPIRATION_TIME_LONG =
- "message_expiration_time_long";
-
- /**
* The data call retry configuration for different types of APN.
* @hide
*/
@@ -1838,6 +1831,13 @@
"support_direct_fdn_dialing_bool";
/**
+ * Int indicating the max number length for FDN
+ * @hide
+ */
+ public static final String KEY_FDN_NUMBER_LENGTH_LIMIT_INT =
+ "fdn_number_length_limit_int";
+
+ /**
* Report IMEI as device id even if it's a CDMA/LTE phone.
*
* @hide
@@ -2840,6 +2840,27 @@
*/
public static final String KEY_5G_WATCHDOG_TIME_MS_LONG =
"5g_watchdog_time_long";
+ /**
+ * Controls whether to switch data to primary from opportunistic subscription
+ * if primary is out of service. This control only affects system or 1st party app
+ * initiated data switch, but will not override data switch initiated by privileged carrier apps
+ * This carrier config is used to disable this feature.
+ * @hide
+ */
+ public static final String KEY_SWITCH_DATA_TO_PRIMARY_IF_PRIMARY_IS_OOS_BOOL =
+ "switch_data_to_primary_if_primary_is_oos_bool";
+
+ /**
+ * Controls back off time in milli seconds for switching back to
+ * opportunistic subscription. This time will be added to
+ * {@link CarrierConfigManager#KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG} to
+ * determine hysteresis time if there is frequent switching
+ * (determined by system app or 1st party app) between primary and opportunistic
+ * subscription.
+ * @hide
+ */
+ public static final String KEY_OPPORTUNISTIC_NETWORK_BACKOFF_TIME_LONG =
+ "opportunistic_network_backoff_time_long";
/**
* Indicates zero or more emergency number prefix(es), because some carrier requires
@@ -2881,6 +2902,16 @@
"always_show_primary_signal_bar_in_opportunistic_network_boolean";
/**
+ * Upon data switching between subscriptions within a carrier group, if switch depends on
+ * validation result, this value defines customized value of how long we wait for validation
+ * success before we fail and revoke the switch.
+ * Time out is in milliseconds.
+ * @hide
+ */
+ public static final String KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG =
+ "data_switch_validation_timeout_long";
+
+ /**
* GPS configs. See android.hardware.gnss@1.0 IGnssConfiguration.
* @hide
*/
@@ -3224,6 +3255,14 @@
public static final String KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY =
"disconnect_cause_play_busytone_int_array";
+ /**
+ * Flag specifying whether to prevent sending CLIR activation("*31#") and deactivation("#31#")
+ * code only without dialing number.
+ * When {@code true}, these are prevented, {@code false} otherwise.
+ */
+ public static final String KEY_PREVENT_CLIR_ACTIVATION_AND_DEACTIVATION_CODE_BOOL =
+ "prevent_clir_activation_and_deactivation_code_bool";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -3346,7 +3385,6 @@
sDefaults.putBoolean(KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL, false);
sDefaults.putBoolean(KEY_ALWAYS_SHOW_EMERGENCY_ALERT_ONOFF_BOOL, false);
sDefaults.putBoolean(KEY_DISABLE_SEVERE_WHEN_EXTREME_DISABLED_BOOL, true);
- sDefaults.putLong(KEY_MESSAGE_EXPIRATION_TIME_LONG, 86400000L);
sDefaults.putStringArray(KEY_CARRIER_DATA_CALL_RETRY_CONFIG_STRINGS, new String[]{
"default:default_randomization=2000,5000,10000,20000,40000,80000:5000,160000:5000,"
+ "320000:5000,640000:5000,1280000:5000,1800000:5000",
@@ -3426,6 +3464,7 @@
sDefaults.putBoolean(KEY_CDMA_HOME_REGISTERED_PLMN_NAME_OVERRIDE_BOOL, false);
sDefaults.putString(KEY_CDMA_HOME_REGISTERED_PLMN_NAME_STRING, "");
sDefaults.putBoolean(KEY_SUPPORT_DIRECT_FDN_DIALING_BOOL, false);
+ sDefaults.putInt(KEY_FDN_NUMBER_LENGTH_LIMIT_INT, 20);
sDefaults.putBoolean(KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL, false);
sDefaults.putBoolean(KEY_SKIP_CF_FAIL_TO_DISABLE_DIALOG_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL, true);
@@ -3630,6 +3669,9 @@
sDefaults.putBoolean(KEY_PING_TEST_BEFORE_DATA_SWITCH_BOOL, true);
/* Default value is 1 hour. */
sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000);
+ sDefaults.putBoolean(KEY_SWITCH_DATA_TO_PRIMARY_IF_PRIMARY_IS_OOS_BOOL, true);
+ /* Default value is 10 seconds. */
+ sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_BACKOFF_TIME_LONG, 10000);
sDefaults.putAll(Gps.getDefaults());
sDefaults.putAll(Wifi.getDefaults());
sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY,
@@ -3657,6 +3699,8 @@
sDefaults.putStringArray(KEY_CARRIER_CERTIFICATE_STRING_ARRAY, null);
sDefaults.putIntArray(KEY_DISCONNECT_CAUSE_PLAY_BUSYTONE_INT_ARRAY,
new int[] {4 /* BUSY */});
+ sDefaults.putBoolean(KEY_PREVENT_CLIR_ACTIVATION_AND_DEACTIVATION_CODE_BOOL, false);
+ sDefaults.putLong(KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG, 2000);
}
/**
diff --git a/telephony/java/com/android/internal/telephony/CbGeoUtils.java b/telephony/java/android/telephony/CbGeoUtils.java
similarity index 94%
rename from telephony/java/com/android/internal/telephony/CbGeoUtils.java
rename to telephony/java/android/telephony/CbGeoUtils.java
index 0b73252..f4ce6e7 100644
--- a/telephony/java/com/android/internal/telephony/CbGeoUtils.java
+++ b/telephony/java/android/telephony/CbGeoUtils.java
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package com.android.internal.telephony;
+package android.telephony;
import android.annotation.NonNull;
-import android.telephony.Rlog;
+import android.annotation.SystemApi;
import android.text.TextUtils;
import java.util.ArrayList;
@@ -30,8 +30,17 @@
* The coordinates used by this utils class are latitude and longitude, but some algorithms in this
* class only use them as coordinates on plane, so the calculation will be inaccurate. So don't use
* this class for anything other then geo-targeting of cellbroadcast messages.
+ * @hide
*/
+@SystemApi
public class CbGeoUtils {
+
+ /**
+ * This class is never instantiated
+ * @hide
+ */
+ private CbGeoUtils() {}
+
/** Geometric interface. */
public interface Geometry {
/**
@@ -39,27 +48,36 @@
* @param p point in latitude, longitude format.
* @return {@code True} if the given point is inside the geometry.
*/
- boolean contains(LatLng p);
+ boolean contains(@NonNull LatLng p);
}
/**
* Tolerance for determining if the value is 0. If the absolute value of a value is less than
* this tolerance, it will be treated as 0.
+ * @hide
*/
public static final double EPS = 1e-7;
- /** The radius of earth. */
+ /**
+ * The radius of earth.
+ * @hide
+ */
public static final int EARTH_RADIUS_METER = 6371 * 1000;
private static final String TAG = "CbGeoUtils";
- /** The TLV tags of WAC, defined in ATIS-0700041 5.2.3 WAC tag coding. */
+ // The TLV tags of WAC, defined in ATIS-0700041 5.2.3 WAC tag coding.
+ /** @hide */
public static final int GEO_FENCING_MAXIMUM_WAIT_TIME = 0x01;
+ /** @hide */
public static final int GEOMETRY_TYPE_POLYGON = 0x02;
+ /** @hide */
public static final int GEOMETRY_TYPE_CIRCLE = 0x03;
- /** The identifier of geometry in the encoded string. */
+ // The identifier of geometry in the encoded string.
+ /** @hide */
private static final String CIRCLE_SYMBOL = "circle";
+ /** @hide */
private static final String POLYGON_SYMBOL = "polygon";
/** Point represent by (latitude, longitude). */
@@ -81,7 +99,8 @@
* @param p the point use to calculate the subtraction result.
* @return the result of this point subtract the given point {@code p}.
*/
- public LatLng subtract(LatLng p) {
+ @NonNull
+ public LatLng subtract(@NonNull LatLng p) {
return new LatLng(lat - p.lat, lng - p.lng);
}
@@ -90,7 +109,7 @@
* @param p the point use to calculate the distance.
* @return the distance in meter.
*/
- public double distance(LatLng p) {
+ public double distance(@NonNull LatLng p) {
double dlat = Math.sin(0.5 * Math.toRadians(lat - p.lat));
double dlng = Math.sin(0.5 * Math.toRadians(lng - p.lng));
double x = dlat * dlat
@@ -106,6 +125,7 @@
/**
* The class represents a simple polygon with at least 3 points.
+ * @hide
*/
public static class Polygon implements Geometry {
/**
@@ -239,7 +259,10 @@
}
}
- /** The class represents a circle. */
+ /**
+ * The class represents a circle.
+ * @hide
+ */
public static class Circle implements Geometry {
private final LatLng mCenter;
private final double mRadiusMeter;
@@ -266,6 +289,7 @@
/**
* Parse the geometries from the encoded string {@code str}. The string must follow the
* geometry encoding specified by {@link android.provider.Telephony.CellBroadcasts#GEOMETRIES}.
+ * @hide
*/
@NonNull
public static List<Geometry> parseGeometriesFromString(@NonNull String str) {
@@ -297,6 +321,7 @@
*
* @param geometries the list of geometry objects need to be encoded.
* @return the encoded string.
+ * @hide
*/
@NonNull
public static String encodeGeometriesToString(List<Geometry> geometries) {
@@ -313,6 +338,7 @@
* {@link android.provider.Telephony.CellBroadcasts#GEOMETRIES}.
* @param geometry the geometry object need to be encoded.
* @return the encoded string.
+ * @hide
*/
@NonNull
private static String encodeGeometryToString(@NonNull Geometry geometry) {
@@ -351,6 +377,7 @@
*
* @param str encoded lat/lng string.
* @Return {@link LatLng} object.
+ * @hide
*/
@NonNull
public static LatLng parseLatLngFromString(@NonNull String str) {
@@ -361,6 +388,7 @@
/**
* @Return the sign of the given value {@code value} with the specified tolerance. Return 1
* means the sign is positive, -1 means negative, 0 means the value will be treated as 0.
+ * @hide
*/
public static int sign(double value) {
if (value > EPS) return 1;
diff --git a/telephony/java/android/telephony/CellBroadcastService.java b/telephony/java/android/telephony/CellBroadcastService.java
index 46eb9df..09e22aa 100644
--- a/telephony/java/android/telephony/CellBroadcastService.java
+++ b/telephony/java/android/telephony/CellBroadcastService.java
@@ -17,12 +17,19 @@
package android.telephony;
import android.annotation.CallSuper;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.Service;
import android.content.Intent;
+import android.os.Bundle;
import android.os.IBinder;
+import android.os.RemoteCallback;
import android.telephony.cdma.CdmaSmsCbProgramData;
+import java.util.List;
+import java.util.function.Consumer;
+
/**
* A service which exposes the cell broadcast handling module to the system.
* <p>
@@ -46,6 +53,7 @@
* </service>
* </manifest>
* }</pre>
+ *
* @hide
*/
@SystemApi
@@ -62,40 +70,59 @@
/**
* Handle a GSM cell broadcast SMS message forwarded from the system.
+ *
* @param slotIndex the index of the slot which received the message
- * @param message the SMS PDU
+ * @param message the SMS PDU
*/
- public abstract void onGsmCellBroadcastSms(int slotIndex, byte[] message);
+ public abstract void onGsmCellBroadcastSms(int slotIndex, @NonNull byte[] message);
/**
* Handle a CDMA cell broadcast SMS message forwarded from the system.
- * @param slotIndex the index of the slot which received the message
- * @param bearerData the CDMA SMS bearer data
+ *
+ * @param slotIndex the index of the slot which received the message
+ * @param bearerData the CDMA SMS bearer data
* @param serviceCategory the CDMA SCPT service category
*/
- public abstract void onCdmaCellBroadcastSms(int slotIndex, byte[] bearerData,
+ public abstract void onCdmaCellBroadcastSms(int slotIndex, @NonNull byte[] bearerData,
@CdmaSmsCbProgramData.Category int serviceCategory);
/**
+ * Handle a CDMA cell broadcast SMS message forwarded from the system.
+ *
+ * @param slotIndex the index of the slot which received the message
+ * @param smsCbProgramData the SMS CB program data of the message
+ * @param originatingAddress the originating address of the message, as a non-separated dial
+ * string
+ * @param callback a callback to run after each cell broadcast receiver has handled
+ * the SCP message. The bundle will contain a non-separated
+ * dial string as and an ArrayList of {@link CdmaSmsCbProgramResults}.
+ */
+ public abstract void onCdmaScpMessage(int slotIndex,
+ @NonNull List<CdmaSmsCbProgramData> smsCbProgramData,
+ @NonNull String originatingAddress, @NonNull Consumer<Bundle> callback);
+
+ /**
* If overriding this method, call through to the super method for any unknown actions.
* {@inheritDoc}
*/
@Override
@CallSuper
- public IBinder onBind(Intent intent) {
+ public IBinder onBind(@Nullable Intent intent) {
return mStubWrapper;
}
/**
* A wrapper around ICellBroadcastService that forwards calls to implementations of
* {@link CellBroadcastService}.
+ *
* @hide
*/
public class ICellBroadcastServiceWrapper extends ICellBroadcastService.Stub {
/**
* Handle a GSM cell broadcast SMS.
+ *
* @param slotIndex the index of the slot which received the broadcast
- * @param message the SMS message PDU
+ * @param message the SMS message PDU
*/
@Override
public void handleGsmCellBroadcastSms(int slotIndex, byte[] message) {
@@ -104,8 +131,9 @@
/**
* Handle a CDMA cell broadcast SMS.
- * @param slotIndex the index of the slot which received the broadcast
- * @param bearerData the CDMA SMS bearer data
+ *
+ * @param slotIndex the index of the slot which received the broadcast
+ * @param bearerData the CDMA SMS bearer data
* @param serviceCategory the CDMA SCPT service category
*/
@Override
@@ -114,5 +142,25 @@
CellBroadcastService.this.onCdmaCellBroadcastSms(slotIndex, bearerData,
serviceCategory);
}
+
+ /**
+ * Handle a CDMA Service Category Program message.
+ *
+ * @param slotIndex the index of the slot which received the message
+ * @param smsCbProgramData the SMS CB program data of the message
+ * @param originatingAddress the originating address of the message
+ * @param callback a callback to run after each cell broadcast receiver has
+ * handled the SCP message
+ */
+ @Override
+ public void handleCdmaScpMessage(int slotIndex,
+ List<CdmaSmsCbProgramData> smsCbProgramData, String originatingAddress,
+ RemoteCallback callback) {
+ Consumer<Bundle> consumer = bundle -> {
+ callback.sendResult(bundle);
+ };
+ CellBroadcastService.this.onCdmaScpMessage(slotIndex, smsCbProgramData,
+ originatingAddress, consumer);
+ }
}
}
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index 1912c60..f9b7f6d 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -194,13 +194,13 @@
/** @hide */
@Override
public void updateLevel(PersistableBundle cc, ServiceState ss) {
- if (mCsiRsrp == CellInfo.UNAVAILABLE) {
+ if (mSsRsrp == CellInfo.UNAVAILABLE) {
mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
- } else if (mCsiRsrp >= SIGNAL_GREAT_THRESHOLD) {
+ } else if (mSsRsrp >= SIGNAL_GREAT_THRESHOLD) {
mLevel = SIGNAL_STRENGTH_GREAT;
- } else if (mCsiRsrp >= SIGNAL_GOOD_THRESHOLD) {
+ } else if (mSsRsrp >= SIGNAL_GOOD_THRESHOLD) {
mLevel = SIGNAL_STRENGTH_GOOD;
- } else if (mCsiRsrp >= SIGNAL_MODERATE_THRESHOLD) {
+ } else if (mSsRsrp >= SIGNAL_MODERATE_THRESHOLD) {
mLevel = SIGNAL_STRENGTH_MODERATE;
} else {
mLevel = SIGNAL_STRENGTH_POOR;
@@ -212,7 +212,7 @@
*
* Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
*
- * @return RSCP in ASU 0..97, 255, or UNAVAILABLE
+ * @return RSRP in ASU 0..97, 255, or UNAVAILABLE
*/
@Override
public int getAsuLevel() {
@@ -231,11 +231,11 @@
}
/**
- * Get the CSI-RSRP as dBm value -140..-44dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
+ * Get the SS-RSRP as dBm value -140..-44dBm or {@link CellInfo#UNAVAILABLE UNAVAILABLE}.
*/
@Override
public int getDbm() {
- return mCsiRsrp;
+ return mSsRsrp;
}
/** @hide */
diff --git a/telephony/java/android/telephony/ICellBroadcastService.aidl b/telephony/java/android/telephony/ICellBroadcastService.aidl
index bcd6cc5..11263d9 100644
--- a/telephony/java/android/telephony/ICellBroadcastService.aidl
+++ b/telephony/java/android/telephony/ICellBroadcastService.aidl
@@ -16,6 +16,9 @@
package android.telephony;
+import android.os.RemoteCallback;
+import android.telephony.cdma.CdmaSmsCbProgramData;
+
/**
* Service bound to by the system to allow custom handling of cell broadcast messages.
* <p>
@@ -29,4 +32,8 @@
/** @see android.telephony.CellBroadcastService#onCdmaCellBroadcastSms */
oneway void handleCdmaCellBroadcastSms(int slotId, in byte[] bearerData, int serviceCategory);
+
+ /** @see android.telephony.CellBroadcastService#onCdmaScpMessage */
+ oneway void handleCdmaScpMessage(int slotId, in List<CdmaSmsCbProgramData> programData,
+ String originatingAddress, in RemoteCallback callback);
}
diff --git a/telephony/java/android/telephony/ImsiEncryptionInfo.java b/telephony/java/android/telephony/ImsiEncryptionInfo.java
index ef2f121..75a79d6 100644
--- a/telephony/java/android/telephony/ImsiEncryptionInfo.java
+++ b/telephony/java/android/telephony/ImsiEncryptionInfo.java
@@ -15,9 +15,11 @@
*/
package android.telephony;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
-import java.util.Date;
import android.util.Log;
import java.security.KeyFactory;
@@ -25,18 +27,18 @@
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
+import java.util.Date;
/**
* Class to represent information sent by the carrier, which will be used to encrypt
* the IMSI + IMPI. The ecryption is being done by WLAN, and the modem.
- *
* @hide
*/
+@SystemApi
public final class ImsiEncryptionInfo implements Parcelable {
private static final String LOG_TAG = "ImsiEncryptionInfo";
-
private final String mcc;
private final String mnc;
private final PublicKey publicKey;
@@ -45,11 +47,13 @@
//Date-Time in UTC when the key will expire.
private final Date expirationTime;
+ /** @hide */
public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier,
byte[] key, Date expirationTime) {
this(mcc, mnc, keyType, keyIdentifier, makeKeyObject(key), expirationTime);
}
+ /** @hide */
public ImsiEncryptionInfo(String mcc, String mnc, int keyType, String keyIdentifier,
PublicKey publicKey, Date expirationTime) {
// todo need to validate that ImsiEncryptionInfo is being created with the correct params.
@@ -63,6 +67,7 @@
this.expirationTime = expirationTime;
}
+ /** @hide */
public ImsiEncryptionInfo(Parcel in) {
int length = in.readInt();
byte b[] = new byte[length];
@@ -75,26 +80,40 @@
expirationTime = new Date(in.readLong());
}
+ /** @hide */
public String getMnc() {
return this.mnc;
}
+ /** @hide */
public String getMcc() {
return this.mcc;
}
+ /**
+ * Returns key identifier, a string that helps the authentication server to locate the
+ * private key to decrypt the permanent identity, or {@code null} when uavailable.
+ */
+ @Nullable
public String getKeyIdentifier() {
return this.keyIdentifier;
}
+ /** @hide */
public int getKeyType() {
return this.keyType;
}
+ /**
+ * Returns the carrier public key that is used for the IMSI encryption,
+ * or {@code null} when uavailable.
+ */
+ @Nullable
public PublicKey getPublicKey() {
return this.publicKey;
}
+ /** @hide */
public Date getExpirationTime() {
return this.expirationTime;
}
@@ -115,7 +134,7 @@
return 0;
}
- public static final @android.annotation.NonNull Parcelable.Creator<ImsiEncryptionInfo> CREATOR =
+ public static final @NonNull Parcelable.Creator<ImsiEncryptionInfo> CREATOR =
new Parcelable.Creator<ImsiEncryptionInfo>() {
@Override
public ImsiEncryptionInfo createFromParcel(Parcel in) {
@@ -129,7 +148,7 @@
};
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
byte[] b = publicKey.getEncoded();
dest.writeInt(b.length);
dest.writeByteArray(b);
diff --git a/telephony/java/android/telephony/LocationAccessPolicy.java b/telephony/java/android/telephony/LocationAccessPolicy.java
index eb744f6..79b3756 100644
--- a/telephony/java/android/telephony/LocationAccessPolicy.java
+++ b/telephony/java/android/telephony/LocationAccessPolicy.java
@@ -18,6 +18,7 @@
import android.Manifest;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppOpsManager;
@@ -59,6 +60,7 @@
public static class LocationPermissionQuery {
public final String callingPackage;
+ public final String callingFeatureId;
public final int callingUid;
public final int callingPid;
public final int minSdkVersionForCoarse;
@@ -66,10 +68,11 @@
public final boolean logAsInfo;
public final String method;
- private LocationPermissionQuery(String callingPackage, int callingUid, int callingPid,
- int minSdkVersionForCoarse, int minSdkVersionForFine, boolean logAsInfo,
- String method) {
+ private LocationPermissionQuery(String callingPackage, @Nullable String callingFeatureId,
+ int callingUid, int callingPid, int minSdkVersionForCoarse,
+ int minSdkVersionForFine, boolean logAsInfo, String method) {
this.callingPackage = callingPackage;
+ this.callingFeatureId = callingFeatureId;
this.callingUid = callingUid;
this.callingPid = callingPid;
this.minSdkVersionForCoarse = minSdkVersionForCoarse;
@@ -80,6 +83,7 @@
public static class Builder {
private String mCallingPackage;
+ private String mCallingFeatureId;
private int mCallingUid;
private int mCallingPid;
private int mMinSdkVersionForCoarse = Integer.MAX_VALUE;
@@ -98,6 +102,14 @@
/**
* Mandatory parameter, used for performing permission checks.
*/
+ public Builder setCallingFeatureId(@Nullable String callingFeatureId) {
+ mCallingFeatureId = callingFeatureId;
+ return this;
+ }
+
+ /**
+ * Mandatory parameter, used for performing permission checks.
+ */
public Builder setCallingUid(int callingUid) {
mCallingUid = callingUid;
return this;
@@ -148,8 +160,8 @@
}
public LocationPermissionQuery build() {
- return new LocationPermissionQuery(mCallingPackage, mCallingUid,
- mCallingPid, mMinSdkVersionForCoarse, mMinSdkVersionForFine,
+ return new LocationPermissionQuery(mCallingPackage, mCallingFeatureId,
+ mCallingUid, mCallingPid, mMinSdkVersionForCoarse, mMinSdkVersionForFine,
mLogAsInfo, mMethod);
}
}
@@ -195,7 +207,7 @@
// Only check the app op if the app has the permission.
int appOpMode = context.getSystemService(AppOpsManager.class)
.noteOpNoThrow(AppOpsManager.permissionToOpCode(permissionToCheck),
- query.callingUid, query.callingPackage);
+ query.callingUid, query.callingPackage, query.callingFeatureId, null);
if (appOpMode == AppOpsManager.MODE_ALLOWED) {
// If the app did everything right, return without logging.
return LocationPermissionResult.ALLOWED;
@@ -339,4 +351,4 @@
}
return false;
}
-}
\ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/SmsCbMessage.java b/telephony/java/android/telephony/SmsCbMessage.java
index dc991b9..3e044e5 100644
--- a/telephony/java/android/telephony/SmsCbMessage.java
+++ b/telephony/java/android/telephony/SmsCbMessage.java
@@ -25,9 +25,7 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.provider.Telephony.CellBroadcasts;
-
-import com.android.internal.telephony.CbGeoUtils;
-import com.android.internal.telephony.CbGeoUtils.Geometry;
+import android.telephony.CbGeoUtils.Geometry;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -414,9 +412,8 @@
/**
* Get the Geo-Fencing Maximum Wait Time.
* @return the time in second.
- * @hide
*/
- public int getMaximumWaitingTime() {
+ public int getMaximumWaitingDuration() {
return mMaximumWaitTimeSec;
}
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index ee291fa..0bf2aa7 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -78,11 +78,6 @@
SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
private static final Object sLockObject = new Object();
- /** @hide */
- public static final int CELL_BROADCAST_RAN_TYPE_GSM = 0;
- /** @hide */
- public static final int CELL_BROADCAST_RAN_TYPE_CDMA = 1;
-
/** SMS record length from TS 51.011 10.5.3
* @hide
*/
@@ -2669,4 +2664,74 @@
}
return SmsManager.SMS_CATEGORY_NOT_SHORT_CODE;
}
+
+ /**
+ * Gets the SMSC address from (U)SIM.
+ *
+ * <p class="note"><strong>Note:</strong> Using this method requires that your app is the
+ * default SMS application, or READ_PRIVILEGED_PHONE_STATE permission, or has the carrier
+ * privileges.</p>
+ *
+ * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this method will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation
+ * is performed on the correct subscription.
+ * </p>
+ *
+ * @return the SMSC address string, null if failed.
+ */
+ @SuppressAutoDoc // for carrier privileges and default SMS application.
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @Nullable
+ public String getSmscAddress() {
+ String smsc = null;
+
+ try {
+ ISms iSms = getISmsService();
+ if (iSms != null) {
+ smsc = iSms.getSmscAddressFromIccEfForSubscriber(
+ getSubscriptionId(), ActivityThread.currentPackageName());
+ }
+ } catch (RemoteException ex) {
+ // ignore it
+ }
+ return smsc;
+ }
+
+ /**
+ * Sets the SMSC address on (U)SIM.
+ *
+ * <p class="note"><strong>Note:</strong> Using this method requires that your app is the
+ * default SMS application, or has {@link android.Manifest.permission#MODIFY_PHONE_STATE}
+ * permission, or has the carrier privileges.</p>
+ *
+ * <p class="note"><strong>Note:</strong> This method will never trigger an SMS disambiguation
+ * dialog. If this method is called on a device that has multiple active subscriptions, this
+ * {@link SmsManager} instance has been created with {@link #getDefault()}, and no user-defined
+ * default subscription is defined, the subscription ID associated with this method will be
+ * INVALID, which will result in the operation being completed on the subscription associated
+ * with logical slot 0. Use {@link #getSmsManagerForSubscriptionId(int)} to ensure the operation
+ * is performed on the correct subscription.
+ * </p>
+ *
+ * @param smsc the SMSC address string.
+ * @return true for success, false otherwise.
+ */
+ @SuppressAutoDoc // for carrier privileges and default SMS application.
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public boolean setSmscAddress(@NonNull String smsc) {
+ try {
+ ISms iSms = getISmsService();
+ if (iSms != null) {
+ return iSms.setSmscAddressOnIccEfForSubscriber(
+ smsc, getSubscriptionId(), ActivityThread.currentPackageName());
+ }
+ } catch (RemoteException ex) {
+ // ignore it
+ }
+ return false;
+ }
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 8425ec1..352d507 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -31,6 +31,7 @@
import android.annotation.SuppressAutoDoc;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.app.BroadcastOptions;
import android.app.PendingIntent;
@@ -49,7 +50,6 @@
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
-import android.os.Message;
import android.os.ParcelUuid;
import android.os.Process;
import android.os.RemoteException;
@@ -156,6 +156,7 @@
*/
@NonNull
@SystemApi
+ @TestApi
public static final Uri WFC_ENABLED_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc");
/**
@@ -175,6 +176,7 @@
*/
@NonNull
@SystemApi
+ @TestApi
public static final Uri ADVANCED_CALLING_ENABLED_CONTENT_URI = Uri.withAppendedPath(
CONTENT_URI, "advanced_calling");
@@ -193,6 +195,7 @@
*/
@NonNull
@SystemApi
+ @TestApi
public static final Uri WFC_MODE_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc_mode");
/**
@@ -210,6 +213,7 @@
*/
@NonNull
@SystemApi
+ @TestApi
public static final Uri WFC_ROAMING_MODE_CONTENT_URI = Uri.withAppendedPath(
CONTENT_URI, "wfc_roaming_mode");
@@ -229,6 +233,7 @@
*/
@NonNull
@SystemApi
+ @TestApi
public static final Uri VT_ENABLED_CONTENT_URI = Uri.withAppendedPath(
CONTENT_URI, "vt_enabled");
@@ -247,6 +252,7 @@
*/
@NonNull
@SystemApi
+ @TestApi
public static final Uri WFC_ROAMING_ENABLED_CONTENT_URI = Uri.withAppendedPath(
CONTENT_URI, "wfc_roaming_enabled");
@@ -2053,13 +2059,13 @@
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public static boolean isValidSlotIndex(int slotIndex) {
- return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getSupportedModemCount();
+ return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getActiveModemCount();
}
/** @hide */
@UnsupportedAppUsage
public static boolean isValidPhoneId(int phoneId) {
- return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getSupportedModemCount();
+ return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getActiveModemCount();
}
/** @hide */
@@ -2372,12 +2378,10 @@
* @param plans the list of plans. The first plan is always the primary and
* most important plan. Any additional plans are secondary and
* may not be displayed or used by decision making logic.
- * The list of all plans must meet the requirements defined in
- * {@link SubscriptionPlan.Builder#setNetworkTypes(int[])}.
* @throws SecurityException if the caller doesn't meet the requirements
* outlined above.
* @throws IllegalArgumentException if plans don't meet the requirements
- * mentioned above.
+ * defined in {@link SubscriptionPlan}.
*/
public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
try {
diff --git a/telephony/java/android/telephony/SubscriptionPlan.java b/telephony/java/android/telephony/SubscriptionPlan.java
index e24eb26..28a5c20 100644
--- a/telephony/java/android/telephony/SubscriptionPlan.java
+++ b/telephony/java/android/telephony/SubscriptionPlan.java
@@ -44,6 +44,14 @@
* as explaining how much mobile data they have remaining, and what will happen
* when they run out.
*
+ * If specifying network types, the developer must supply at least one plan
+ * that applies to all network types (default), and all additional plans
+ * may not include a particular network type more than once.
+ * This is enforced by {@link SubscriptionManager} when setting the plans.
+ *
+ * Plan selection will prefer plans that have specific network types defined
+ * over plans that apply to all network types.
+ *
* @see SubscriptionManager#setSubscriptionPlans(int, java.util.List)
* @see SubscriptionManager#getSubscriptionPlans(int)
*/
@@ -213,7 +221,7 @@
/**
* Return an array containing all {@link NetworkType}s this SubscriptionPlan applies to.
- * A null array means this SubscriptionPlan applies to all network types.
+ * A null value means this SubscriptionPlan applies to all network types.
*/
public @Nullable @NetworkType int[] getNetworkTypes() {
return networkTypes;
@@ -372,20 +380,13 @@
/**
* Set the network types this SubscriptionPlan applies to.
- * The developer must supply at least one plan that applies to all network types (default),
- * and all additional plans may not include a particular network type more than once.
- * Plan selection will prefer plans that have specific network types defined
- * over plans that apply to all network types.
*
* @param networkTypes a set of all {@link NetworkType}s that apply to this plan.
- * A null value or empty array means the plan applies to all network types.
+ * A null value means the plan applies to all network types,
+ * and an empty array means the plan applies to no network types.
*/
public @NonNull Builder setNetworkTypes(@Nullable @NetworkType int[] networkTypes) {
- if (networkTypes == null || networkTypes.length == 0) {
- plan.networkTypes = null;
- } else {
- plan.networkTypes = networkTypes;
- }
+ plan.networkTypes = networkTypes;
return this;
}
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 2eb4809..5a63eb0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -110,6 +110,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -197,12 +198,29 @@
/** @hide */
static public final int OTASP_SIM_UNPROVISIONED = 5;
- /** @hide */
+ /**
+ * Used in carrier Wi-Fi for IMSI + IMPI encryption, this indicates a public key that's
+ * available for use in ePDG links.
+ *
+ * @hide
+ */
+ @SystemApi
static public final int KEY_TYPE_EPDG = 1;
- /** @hide */
+ /**
+ * Used in carrier Wi-Fi for IMSI + IMPI encryption, this indicates a public key that's
+ * available for use in WLAN links.
+ *
+ * @hide
+ */
+ @SystemApi
static public final int KEY_TYPE_WLAN = 2;
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"KEY_TYPE_"}, value = {KEY_TYPE_EPDG, KEY_TYPE_WLAN})
+ public @interface KeyType {}
+
/**
* No Single Radio Voice Call Continuity (SRVCC) handover is active.
* See TS 23.216 for more information.
@@ -308,7 +326,11 @@
mSubId = subId;
Context appContext = context.getApplicationContext();
if (appContext != null) {
- mContext = appContext;
+ if (Objects.equals(context.getFeatureId(), appContext.getFeatureId())) {
+ mContext = appContext;
+ } else {
+ mContext = appContext.createFeatureContext(context.getFeatureId());
+ }
} else {
mContext = context;
}
@@ -343,6 +365,16 @@
return ActivityThread.currentOpPackageName();
}
+ private String getFeatureId() {
+ // For legacy reasons the TelephonyManager has API for getting
+ // a static instance with no context set preventing us from
+ // getting the feature Id.
+ if (mContext != null) {
+ return mContext.getFeatureId();
+ }
+ return null;
+ }
+
private boolean isSystemProcess() {
return Process.myUid() == Process.SYSTEM_UID;
}
@@ -1873,7 +1905,12 @@
if (telephony == null) return null;
try {
- return telephony.getMeidForSlot(slotIndex, getOpPackageName());
+ String meid = telephony.getMeidForSlot(slotIndex, getOpPackageName());
+ if (TextUtils.isEmpty(meid)) {
+ Log.d(TAG, "getMeid: return null because MEID is not available");
+ return null;
+ }
+ return meid;
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -2002,7 +2039,8 @@
return null;
}
- Bundle bundle = telephony.getCellLocation(mContext.getOpPackageName());
+ Bundle bundle = telephony.getCellLocation(mContext.getOpPackageName(),
+ mContext.getFeatureId());
if (bundle == null || bundle.isEmpty()) {
Rlog.d(TAG, "getCellLocation returning null because CellLocation is unavailable");
return null;
@@ -2090,7 +2128,8 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getNeighboringCellInfo(mContext.getOpPackageName());
+ return telephony.getNeighboringCellInfo(mContext.getOpPackageName(),
+ mContext.getFeatureId());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
@@ -3869,25 +3908,27 @@
}
/**
- * Returns Carrier specific information that will be used to encrypt the IMSI and IMPI.
- * This includes the public key and the key identifier. For multi-sim devices, if no subId
- * has been specified, we will return the value for the dafault data sim.
- * Return null if it is unavailable.
+ * Returns carrier specific information that will be used to encrypt the IMSI and IMPI,
+ * including the public key and the key identifier; or {@code null} if not available.
* <p>
- * Requires Permission:
- * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
- * @param keyType whether the key is being used for wlan or epdg. Valid key types are
- * {@link TelephonyManager#KEY_TYPE_EPDG} or
- * {@link TelephonyManager#KEY_TYPE_WLAN}.
+ * For a multi-sim device, the dafault data sim is used if not specified.
+ * <p>
+ * Requires Permission: READ_PRIVILEGED_PHONE_STATE.
+ *
+ * @param keyType whether the key is being used for EPDG or WLAN. Valid values are
+ * {@link #KEY_TYPE_EPDG} or {@link #KEY_TYPE_WLAN}.
* @return ImsiEncryptionInfo Carrier specific information that will be used to encrypt the
* IMSI and IMPI. This includes the public key and the key identifier. This information
- * will be stored in the device keystore. The system will return a null when no key was
- * found, and the carrier does not require a key. The system will throw
- * IllegalArgumentException when an invalid key is sent or when key is required but
+ * will be stored in the device keystore. {@code null} will be returned when no key is
+ * found, and the carrier does not require a key.
+ * @throws IllegalArgumentException when an invalid key is found or when key is required but
* not found.
* @hide
*/
- public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType) {
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SystemApi
+ @Nullable
+ public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(@KeyType int keyType) {
try {
IPhoneSubInfo info = getSubscriberInfo();
if (info == null) {
@@ -3915,14 +3956,21 @@
}
/**
- * Resets the Carrier Keys in the database. This involves 2 steps:
+ * Resets the carrier keys used to encrypt the IMSI and IMPI.
+ * <p>
+ * This involves 2 steps:
* 1. Delete the keys from the database.
* 2. Send an intent to download new Certificates.
* <p>
- * Requires Permission:
- * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
+ * For a multi-sim device, the dafault data sim is used if not specified.
+ * <p>
+ * Requires Permission: MODIFY_PHONE_STATE.
+ *
+ * @see #getCarrierInfoForImsiEncryption
* @hide
*/
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ @SystemApi
public void resetCarrierKeysForImsiEncryption() {
try {
IPhoneSubInfo info = getSubscriberInfo();
@@ -3949,7 +3997,7 @@
* @return true if the digit at position keyType is 1, else false.
* @hide
*/
- private static boolean isKeyEnabled(int keyAvailability, int keyType) {
+ private static boolean isKeyEnabled(int keyAvailability, @KeyType int keyType) {
int returnValue = (keyAvailability >> (keyType - 1)) & 1;
return (returnValue == 1) ? true : false;
}
@@ -3958,7 +4006,7 @@
* If Carrier requires Imsi to be encrypted.
* @hide
*/
- private boolean isImsiEncryptionRequired(int subId, int keyType) {
+ private boolean isImsiEncryptionRequired(int subId, @KeyType int keyType) {
CarrierConfigManager configManager =
(CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
if (configManager == null) {
@@ -5483,8 +5531,7 @@
ITelephony telephony = getITelephony();
if (telephony == null)
return null;
- return telephony.getAllCellInfo(
- getOpPackageName());
+ return telephony.getAllCellInfo(getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
@@ -5576,7 +5623,7 @@
errorCode,
createThrowableByClassName(exceptionName, message))));
}
- }, getOpPackageName());
+ }, getOpPackageName(), getFeatureId());
} catch (RemoteException ex) {
}
}
@@ -5618,7 +5665,7 @@
errorCode,
createThrowableByClassName(exceptionName, message))));
}
- }, getOpPackageName(), workSource);
+ }, getOpPackageName(), getFeatureId(), workSource);
} catch (RemoteException ex) {
}
}
@@ -7442,7 +7489,8 @@
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getCellNetworkScanResults(getSubId(), getOpPackageName());
+ return telephony.getCellNetworkScanResults(getSubId(), getOpPackageName(),
+ getFeatureId());
}
} catch (RemoteException ex) {
Rlog.e(TAG, "getAvailableNetworks RemoteException", ex);
@@ -7497,7 +7545,7 @@
}
}
return mTelephonyScanManager.requestNetworkScan(getSubId(), request, executor, callback,
- getOpPackageName());
+ getOpPackageName(), getFeatureId());
}
/**
@@ -7981,6 +8029,7 @@
/** @hide */
@SystemApi
+ @TestApi
public List<String> getCarrierPackageNamesForIntent(Intent intent) {
return getCarrierPackageNamesForIntentAndPhone(intent, getPhoneId());
}
@@ -9493,16 +9542,28 @@
return returnValue;
}
- private int getSubIdForPhoneAccountHandle(PhoneAccountHandle phoneAccountHandle) {
+ /**
+ * Returns the subscription ID for the given phone account handle.
+ *
+ * @param phoneAccountHandle the phone account handle for outgoing calls
+ * @return subscription ID for the given phone account handle; or
+ * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}
+ * if not available; or throw a SecurityException if the caller doesn't have the
+ * permission.
+ */
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ public int getSubIdForPhoneAccountHandle(@NonNull PhoneAccountHandle phoneAccountHandle) {
int retval = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
try {
- ITelecomService service = getTelecomService();
+ ITelephony service = getITelephony();
if (service != null) {
- retval = getSubIdForPhoneAccount(service.getPhoneAccount(phoneAccountHandle));
+ retval = service.getSubIdForPhoneAccountHandle(
+ phoneAccountHandle, mContext.getOpPackageName());
}
- } catch (RemoteException e) {
+ } catch (RemoteException ex) {
+ Log.e(TAG, "getSubIdForPhoneAccountHandle RemoteException", ex);
+ ex.rethrowAsRuntimeException();
}
-
return retval;
}
@@ -9515,8 +9576,29 @@
try {
Log.d(TAG, "factoryReset: subId=" + subId);
ITelephony telephony = getITelephony();
- if (telephony != null)
+ if (telephony != null) {
telephony.factoryReset(subId);
+ }
+ } catch (RemoteException e) {
+ }
+ }
+
+
+ /**
+ * Resets Telephony and IMS settings back to factory defaults only for the subscription
+ * associated with this instance.
+ * @see #createForSubscriptionId(int)
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(Manifest.permission.CONNECTIVITY_INTERNAL)
+ public void resetSettings() {
+ try {
+ Log.d(TAG, "resetSettings: subId=" + getSubId());
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ telephony.factoryReset(getSubId());
+ }
} catch (RemoteException e) {
}
}
@@ -9614,7 +9696,8 @@
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.getServiceStateForSubscriber(subId, getOpPackageName());
+ return service.getServiceStateForSubscriber(subId, getOpPackageName(),
+ getFeatureId());
}
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelephony#getServiceStateForSubscriber", e);
@@ -10869,6 +10952,16 @@
}
/**
+ * Broadcast intent action for Ota emergency number database installation complete.
+ *
+ * @hide
+ */
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @SystemApi
+ public static final String ACTION_OTA_EMERGENCY_NUMBER_DB_INSTALLED =
+ "android.telephony.action.OTA_EMERGENCY_NUMBER_DB_INSTALLED";
+
+ /**
* Returns whether {@link TelephonyManager#ACTION_EMERGENCY_ASSISTANCE emergency assistance} is
* available on the device.
* <p>
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index 9ff8515..96b6db7 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -18,6 +18,7 @@
import static com.android.internal.util.Preconditions.checkNotNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.os.Binder;
import android.os.Bundle;
@@ -195,18 +196,21 @@
*
* @param request Contains all the RAT with bands/channels that need to be scanned.
* @param callback Returns network scan results or errors.
+ * @param callingPackage The package name of the caller
+ * @param callingFeatureId The feature id inside of the calling package
* @return A NetworkScan obj which contains a callback which can stop the scan.
* @hide
*/
public NetworkScan requestNetworkScan(int subId,
NetworkScanRequest request, Executor executor, NetworkScanCallback callback,
- String callingPackage) {
+ String callingPackage, @Nullable String callingFeatureId) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
synchronized (mScanInfo) {
int scanId = telephony.requestNetworkScan(
- subId, request, mMessenger, new Binder(), callingPackage);
+ subId, request, mMessenger, new Binder(), callingPackage,
+ callingFeatureId);
if (scanId == INVALID_SCAN_ID) {
Rlog.e(TAG, "Failed to initiate network scan");
return null;
diff --git a/telephony/java/android/telephony/cdma/CdmaSmsCbProgramData.aidl b/telephony/java/android/telephony/cdma/CdmaSmsCbProgramData.aidl
new file mode 100644
index 0000000..a648a0e
--- /dev/null
+++ b/telephony/java/android/telephony/cdma/CdmaSmsCbProgramData.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** @hide */
+package android.telephony.cdma;
+
+parcelable CdmaSmsCbProgramData;
+
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 2161dcb..60774e7 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1191,7 +1191,7 @@
&& !other.canHandleType(TYPE_DUN)
&& Objects.equals(this.mApnName, other.mApnName)
&& !typeSameAny(this, other)
- && xorEquals(this.mProxyAddress, other.mProxyAddress)
+ && xorEqualsString(this.mProxyAddress, other.mProxyAddress)
&& xorEqualsInt(this.mProxyPort, other.mProxyPort)
&& xorEquals(this.mProtocol, other.mProtocol)
&& xorEquals(this.mRoamingProtocol, other.mRoamingProtocol)
@@ -1200,7 +1200,7 @@
&& Objects.equals(this.mMvnoType, other.mMvnoType)
&& Objects.equals(this.mMvnoMatchData, other.mMvnoMatchData)
&& xorEquals(this.mMmsc, other.mMmsc)
- && xorEquals(this.mMmsProxyAddress, other.mMmsProxyAddress)
+ && xorEqualsString(this.mMmsProxyAddress, other.mMmsProxyAddress)
&& xorEqualsInt(this.mMmsProxyPort, other.mMmsProxyPort))
&& Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
&& Objects.equals(mApnSetId, other.mApnSetId)
@@ -1213,6 +1213,11 @@
return first == null || second == null || first.equals(second);
}
+ // Equal or one is null.
+ private boolean xorEqualsString(String first, String second) {
+ return TextUtils.isEmpty(first) || TextUtils.isEmpty(second) || first.equals(second);
+ }
+
// Equal or one is not specified.
private boolean xorEqualsInt(int first, int second) {
return first == UNSPECIFIED_INT || second == UNSPECIFIED_INT
@@ -1939,8 +1944,9 @@
* {@link ApnSetting} built from this builder otherwise.
*/
public ApnSetting build() {
- if ((mApnTypeBitmask & TYPE_ALL) == 0 || TextUtils.isEmpty(mApnName)
- || TextUtils.isEmpty(mEntryName)) {
+ if ((mApnTypeBitmask & (TYPE_DEFAULT | TYPE_MMS | TYPE_SUPL | TYPE_DUN | TYPE_HIPRI |
+ TYPE_FOTA | TYPE_IMS | TYPE_CBS | TYPE_IA | TYPE_EMERGENCY | TYPE_MCX)) == 0
+ || TextUtils.isEmpty(mApnName) || TextUtils.isEmpty(mEntryName)) {
return null;
}
return new ApnSetting(this);
diff --git a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
index 79cdfef..9f09d7a 100644
--- a/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
+++ b/telephony/java/android/telephony/ims/ImsCallForwardInfo.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,6 +33,7 @@
* @hide
*/
@SystemApi
+@TestApi
public final class ImsCallForwardInfo implements Parcelable {
/**
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index 4ddeb90..b0ff5dc 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Bundle;
import android.os.Parcel;
@@ -45,6 +46,7 @@
* @hide
*/
@SystemApi
+@TestApi
public final class ImsCallProfile implements Parcelable {
private static final String TAG = "ImsCallProfile";
diff --git a/telephony/java/android/telephony/ims/ImsCallSessionListener.java b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
index a09844d..e11886f 100644
--- a/telephony/java/android/telephony/ims/ImsCallSessionListener.java
+++ b/telephony/java/android/telephony/ims/ImsCallSessionListener.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.RemoteException;
import android.telephony.CallQuality;
import android.telephony.ims.aidl.IImsCallSessionListener;
@@ -36,6 +37,7 @@
// TODO: APIs in here do not conform to API guidelines yet. This can be changed if
// ImsCallSessionListenerConverter is also changed.
@SystemApi
+@TestApi
public class ImsCallSessionListener {
private final IImsCallSessionListener mListener;
diff --git a/telephony/java/android/telephony/ims/ImsConferenceState.java b/telephony/java/android/telephony/ims/ImsConferenceState.java
index 6f062f4..eb6c12c 100644
--- a/telephony/java/android/telephony/ims/ImsConferenceState.java
+++ b/telephony/java/android/telephony/ims/ImsConferenceState.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -36,6 +37,7 @@
* @hide
*/
@SystemApi
+@TestApi
public final class ImsConferenceState implements Parcelable {
/**
* conference-info : user
diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java
index 6187e67..39af2e7 100644
--- a/telephony/java/android/telephony/ims/ImsException.java
+++ b/telephony/java/android/telephony/ims/ImsException.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.content.pm.PackageManager;
import android.telephony.SubscriptionManager;
import android.text.TextUtils;
@@ -32,6 +33,7 @@
* @hide
*/
@SystemApi
+@TestApi
public final class ImsException extends Exception {
/**
diff --git a/telephony/java/android/telephony/ims/ImsExternalCallState.java b/telephony/java/android/telephony/ims/ImsExternalCallState.java
index eb2ebca..177d9b3 100644
--- a/telephony/java/android/telephony/ims/ImsExternalCallState.java
+++ b/telephony/java/android/telephony/ims/ImsExternalCallState.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -34,6 +35,7 @@
* @hide
*/
@SystemApi
+@TestApi
public final class ImsExternalCallState implements Parcelable {
private static final String TAG = "ImsExternalCallState";
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 2fad847..eb0e2f7 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -24,31 +24,28 @@
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.content.Context;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.net.Uri;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.telephony.AccessNetworkConstants;
+import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.ims.aidl.IImsCapabilityCallback;
-import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.ITelephony;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.HashMap;
-import java.util.Map;
import java.util.concurrent.Executor;
+import java.util.function.Consumer;
/**
* A manager for the MmTel (Multimedia Telephony) feature of an IMS network, given an associated
@@ -62,9 +59,8 @@
* @hide
*/
@SystemApi
-public class ImsMmTelManager {
-
- private static final String TAG = "ImsMmTelManager";
+@TestApi
+public class ImsMmTelManager implements RegistrationManager {
/**
* @hide
@@ -97,94 +93,18 @@
* Callback class for receiving IMS network Registration callback events.
* @see #registerImsRegistrationCallback(Executor, RegistrationCallback) (RegistrationCallback)
* @see #unregisterImsRegistrationCallback(RegistrationCallback)
+ * @deprecated Use {@link RegistrationManager.RegistrationCallback} instead.
*/
- public static class RegistrationCallback {
-
- private static class RegistrationBinder extends IImsRegistrationCallback.Stub {
-
- // Translate ImsRegistrationImplBase API to new AccessNetworkConstant because WLAN
- // and WWAN are more accurate constants.
- private static final Map<Integer, Integer> IMS_REG_TO_ACCESS_TYPE_MAP =
- new HashMap<Integer, Integer>() {{
- // Map NONE to -1 to make sure that we handle the REGISTRATION_TECH_NONE
- // case, since it is defined.
- put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE, -1);
- put(ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
- AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
- put(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
- AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
- }};
-
- private final RegistrationCallback mLocalCallback;
- private Executor mExecutor;
-
- RegistrationBinder(RegistrationCallback localCallback) {
- mLocalCallback = localCallback;
- }
-
- @Override
- public void onRegistered(int imsRadioTech) {
- if (mLocalCallback == null) return;
-
- Binder.withCleanCallingIdentity(() -> mExecutor.execute(() ->
- mLocalCallback.onRegistered(getAccessType(imsRadioTech))));
- }
-
- @Override
- public void onRegistering(int imsRadioTech) {
- if (mLocalCallback == null) return;
-
- Binder.withCleanCallingIdentity(() -> mExecutor.execute(() ->
- mLocalCallback.onRegistering(getAccessType(imsRadioTech))));
- }
-
- @Override
- public void onDeregistered(ImsReasonInfo info) {
- if (mLocalCallback == null) return;
-
- Binder.withCleanCallingIdentity(() ->
- mExecutor.execute(() -> mLocalCallback.onUnregistered(info)));
- }
-
- @Override
- public void onTechnologyChangeFailed(int imsRadioTech, ImsReasonInfo info) {
- if (mLocalCallback == null) return;
-
- Binder.withCleanCallingIdentity(() ->
- mExecutor.execute(() -> mLocalCallback.onTechnologyChangeFailed(
- getAccessType(imsRadioTech), info)));
- }
-
- @Override
- public void onSubscriberAssociatedUriChanged(Uri[] uris) {
- if (mLocalCallback == null) return;
-
- Binder.withCleanCallingIdentity(() ->
- mExecutor.execute(() ->
- mLocalCallback.onSubscriberAssociatedUriChanged(uris)));
- }
-
- private void setExecutor(Executor executor) {
- mExecutor = executor;
- }
-
- private static int getAccessType(int regType) {
- if (!IMS_REG_TO_ACCESS_TYPE_MAP.containsKey(regType)) {
- Log.w("ImsMmTelManager", "RegistrationBinder - invalid regType returned: "
- + regType);
- return -1;
- }
- return IMS_REG_TO_ACCESS_TYPE_MAP.get(regType);
- }
- }
-
- private final RegistrationBinder mBinder = new RegistrationBinder(this);
+ // Do not add to this class, add to RegistrationManager.RegistrationCallback instead.
+ @Deprecated
+ public static class RegistrationCallback extends RegistrationManager.RegistrationCallback {
/**
* Notifies the framework when the IMS Provider is registered to the IMS network.
*
* @param imsTransportType the radio access technology.
*/
+ @Override
public void onRegistered(@AccessNetworkConstants.TransportType int imsTransportType) {
}
@@ -193,6 +113,7 @@
*
* @param imsTransportType the radio access technology.
*/
+ @Override
public void onRegistering(@AccessNetworkConstants.TransportType int imsTransportType) {
}
@@ -201,6 +122,7 @@
*
* @param info the {@link ImsReasonInfo} associated with why registration was disconnected.
*/
+ @Override
public void onUnregistered(@Nullable ImsReasonInfo info) {
}
@@ -210,33 +132,11 @@
* @param imsTransportType The transport type that has failed to handover registration to.
* @param info A {@link ImsReasonInfo} that identifies the reason for failure.
*/
+ @Override
public void onTechnologyChangeFailed(
@AccessNetworkConstants.TransportType int imsTransportType,
@Nullable ImsReasonInfo info) {
}
-
- /**
- * Returns a list of subscriber {@link Uri}s associated with this IMS subscription when
- * it changes. Per RFC3455, an associated URI is a URI that the service provider has
- * allocated to a user for their own usage. A user's phone number is typically one of the
- * associated URIs.
- * @param uris new array of subscriber {@link Uri}s that are associated with this IMS
- * subscription.
- * @hide
- */
- public void onSubscriberAssociatedUriChanged(@Nullable Uri[] uris) {
- }
-
- /**@hide*/
- public final IImsRegistrationCallback getBinder() {
- return mBinder;
- }
-
- /**@hide*/
- //Only exposed as public for compatibility with deprecated ImsManager APIs.
- public void setExecutor(Executor executor) {
- mBinder.setExecutor(executor);
- }
}
/**
@@ -311,7 +211,7 @@
}
}
- private int mSubId;
+ private final int mSubId;
/**
* Create an instance of {@link ImsMmTelManager} for the subscription id specified.
@@ -356,7 +256,10 @@
* the {@link ImsService} associated with the subscription is not available. This can happen if
* the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
* reason.
+ * @deprecated Use {@link RegistrationManager#registerImsRegistrationCallback(Executor,
+ * RegistrationManager.RegistrationCallback)} instead.
*/
+ @Deprecated
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull RegistrationCallback c) throws ImsException {
@@ -366,10 +269,6 @@
if (executor == null) {
throw new IllegalArgumentException("Must include a non-null Executor.");
}
- if (!isImsAvailableOnDevice()) {
- throw new ImsException("IMS not available on device.",
- ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
- }
c.setExecutor(executor);
try {
getITelephony().registerImsRegistrationCallback(mSubId, c.getBinder());
@@ -378,13 +277,34 @@
// Rethrow as runtime error to keep API compatible.
throw new IllegalArgumentException(e.getMessage());
} else {
- throw new RuntimeException(e.getMessage());
+ throw new ImsException(e.getMessage(), e.errorCode);
}
} catch (RemoteException | IllegalStateException e) {
throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
+ /**{@inheritDoc}*/
+ @Override
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull RegistrationManager.RegistrationCallback c) throws ImsException {
+ if (c == null) {
+ throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
+ }
+ if (executor == null) {
+ throw new IllegalArgumentException("Must include a non-null Executor.");
+ }
+ c.setExecutor(executor);
+ try {
+ getITelephony().registerImsRegistrationCallback(mSubId, c.getBinder());
+ } catch (ServiceSpecificException e) {
+ throw new ImsException(e.getMessage(), e.errorCode);
+ } catch (RemoteException | IllegalStateException e) {
+ throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ }
+
/**
* Removes an existing {@link RegistrationCallback}.
*
@@ -395,7 +315,10 @@
* @param c The {@link RegistrationCallback} to be removed.
* @see SubscriptionManager.OnSubscriptionsChangedListener
* @see #registerImsRegistrationCallback(Executor, RegistrationCallback)
+ * @deprecated Use {@link #unregisterImsRegistrationCallback(
+ * RegistrationManager.RegistrationCallback)}.
*/
+ @Deprecated
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c) {
if (c == null) {
@@ -408,6 +331,69 @@
}
}
+ /**{@inheritDoc}*/
+ @Override
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void unregisterImsRegistrationCallback(
+ @NonNull RegistrationManager.RegistrationCallback c) {
+ if (c == null) {
+ throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
+ }
+ try {
+ getITelephony().unregisterImsRegistrationCallback(mSubId, c.getBinder());
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**{@inheritDoc}*/
+ @Override
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void getRegistrationState(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @ImsRegistrationState Consumer<Integer> stateCallback) {
+ if (stateCallback == null) {
+ throw new IllegalArgumentException("Must include a non-null callback.");
+ }
+ if (executor == null) {
+ throw new IllegalArgumentException("Must include a non-null Executor.");
+ }
+ try {
+ getITelephony().getImsMmTelRegistrationState(mSubId, new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> stateCallback.accept(result));
+ }
+ });
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**{@inheritDoc}*/
+ @Override
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void getRegistrationTransportType(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @AccessNetworkConstants.TransportType
+ Consumer<Integer> transportTypeCallback) {
+ if (transportTypeCallback == null) {
+ throw new IllegalArgumentException("Must include a non-null callback.");
+ }
+ if (executor == null) {
+ throw new IllegalArgumentException("Must include a non-null Executor.");
+ }
+ try {
+ getITelephony().getImsMmTelRegistrationTransportType(mSubId,
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> transportTypeCallback.accept(result));
+ }
+ });
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
/**
* Registers a {@link CapabilityCallback} with the system, which will provide MmTel service
* availability updates for the subscription specified in
@@ -416,7 +402,7 @@
*
* Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
* subscription changed events and call
- * {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up.
+ * {@link #unregisterMmTelCapabilityCallback(CapabilityCallback)} to clean up.
*
* When the callback is registered, it will initiate the callback c to be called with the
* current capabilities.
@@ -441,10 +427,6 @@
if (executor == null) {
throw new IllegalArgumentException("Must include a non-null Executor.");
}
- if (!isImsAvailableOnDevice()) {
- throw new ImsException("IMS not available on device.",
- ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
- }
c.setExecutor(executor);
try {
getITelephony().registerMmTelCapabilityCallback(mSubId, c.getBinder());
@@ -453,7 +435,7 @@
// Rethrow as runtime error to keep API compatible.
throw new IllegalArgumentException(e.getMessage());
} else {
- throw new RuntimeException(e.getMessage());
+ throw new ImsException(e.getMessage(), e.errorCode);
}
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
@@ -618,6 +600,46 @@
}
/**
+ * Query whether or not the requested MmTel capability is supported by the carrier on the
+ * specified network transport.
+ * <p>
+ * This is a configuration option and does not change. The only time this may change is if a
+ * new IMS configuration is loaded when there is a
+ * {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED} broadcast for this subscription.
+ * @param capability The capability that is being queried for support on the carrier network.
+ * @param transportType The transport type of the capability to check support for.
+ * @param executor The executor that the callback will be called with.
+ * @param callback A consumer containing a Boolean result specifying whether or not the
+ * capability is supported on this carrier network for the transport specified.
+ * @throws ImsException if the subscription is no longer valid or the IMS service is not
+ * available.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void isSupported(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
+ @AccessNetworkConstants.TransportType int transportType,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<Boolean> callback) throws ImsException {
+ if (callback == null) {
+ throw new IllegalArgumentException("Must include a non-null Consumer.");
+ }
+ if (executor == null) {
+ throw new IllegalArgumentException("Must include a non-null Executor.");
+ }
+ try {
+ getITelephony().isMmTelCapabilitySupported(mSubId, new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> callback.accept(result == 1));
+ }
+ }, capability, transportType);
+ } catch (ServiceSpecificException sse) {
+ throw new ImsException(sse.getMessage(), sse.errorCode);
+ } catch (RemoteException e) {
+ e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
* The user's setting for whether or not they have enabled the "Video Calling" setting.
*
* @throws IllegalArgumentException if the subscription associated with this operation is not
@@ -940,7 +962,7 @@
* @see android.telephony.CarrierConfigManager#KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- boolean isTtyOverVolteEnabled() {
+ public boolean isTtyOverVolteEnabled() {
try {
return getITelephony().isTtyOverVolteEnabled(mSubId);
} catch (ServiceSpecificException e) {
@@ -955,20 +977,39 @@
}
}
- private static boolean isImsAvailableOnDevice() {
- IPackageManager pm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
- if (pm == null) {
- // For some reason package manger is not available.. This will fail internally anyways,
- // so do not throw error and allow.
- return true;
+ /**
+ * Get the status of the MmTel Feature registered on this subscription.
+ * @param callback A callback containing an Integer describing the current state of the
+ * MmTel feature, Which will be one of the following:
+ * {@link ImsFeature#STATE_UNAVAILABLE},
+ * {@link ImsFeature#STATE_INITIALIZING},
+ * {@link ImsFeature#STATE_READY}. Will be called using the executor
+ * specified when the service state has been retrieved from the IMS service.
+ * @param executor The executor that will be used to call the callback.
+ * @throws ImsException if the IMS service associated with this subscription is not available or
+ * the IMS service is not available.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public void getFeatureState(@NonNull @ImsFeature.ImsState Consumer<Integer> callback,
+ @NonNull @CallbackExecutor Executor executor) throws ImsException {
+ if (callback == null) {
+ throw new IllegalArgumentException("Must include a non-null Consumer.");
+ }
+ if (executor == null) {
+ throw new IllegalArgumentException("Must include a non-null Executor.");
}
try {
- return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS, 0);
+ getITelephony().getImsMmTelFeatureState(mSubId, new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> callback.accept(result));
+ }
+ });
+ } catch (ServiceSpecificException sse) {
+ throw new ImsException(sse.getMessage(), sse.errorCode);
} catch (RemoteException e) {
- // For some reason package manger is not available.. This will fail internally anyways,
- // so do not throw error and allow.
+ e.rethrowAsRuntimeException();
}
- return true;
}
private static ITelephony getITelephony() {
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index 3c343dd..6432016 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -22,12 +22,14 @@
import android.annotation.RequiresPermission;
import android.content.Context;
import android.os.Binder;
+import android.telephony.AccessNetworkConstants;
import android.telephony.SubscriptionManager;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.RcsFeature;
import java.util.concurrent.Executor;
+import java.util.function.Consumer;
/**
* Manager for interfacing with the framework RCS services, including the User Capability Exchange
@@ -36,7 +38,7 @@
* Use {@link #createForSubscriptionId(Context, int)} to create an instance of this manager.
* @hide
*/
-public class ImsRcsManager {
+public class ImsRcsManager implements RegistrationManager {
/**
* Receives RCS availability status updates from the ImsService.
@@ -136,6 +138,64 @@
mSubId = subId;
}
+ /**{@inheritDoc}*/
+ @Override
+ public void registerImsRegistrationCallback(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull RegistrationCallback c)
+ throws ImsException {
+ if (c == null) {
+ throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
+ }
+ if (executor == null) {
+ throw new IllegalArgumentException("Must include a non-null Executor.");
+ }
+ c.setExecutor(executor);
+ throw new UnsupportedOperationException("registerImsRegistrationCallback is not"
+ + "supported.");
+ }
+
+ /**{@inheritDoc}*/
+ @Override
+ public void unregisterImsRegistrationCallback(
+ @NonNull RegistrationManager.RegistrationCallback c) {
+ if (c == null) {
+ throw new IllegalArgumentException("Must include a non-null RegistrationCallback.");
+ }
+ throw new UnsupportedOperationException("unregisterImsRegistrationCallback is not"
+ + "supported.");
+ }
+
+ /**{@inheritDoc}*/
+ @Override
+ public void getRegistrationState(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @ImsRegistrationState Consumer<Integer> stateCallback) {
+ if (stateCallback == null) {
+ throw new IllegalArgumentException("Must include a non-null stateCallback.");
+ }
+ if (executor == null) {
+ throw new IllegalArgumentException("Must include a non-null Executor.");
+ }
+ throw new UnsupportedOperationException("getRegistrationState is not"
+ + "supported.");
+ }
+
+ /**{@inheritDoc}*/
+ @Override
+ public void getRegistrationTransportType(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @AccessNetworkConstants.TransportType
+ Consumer<Integer> transportTypeCallback) {
+ if (transportTypeCallback == null) {
+ throw new IllegalArgumentException("Must include a non-null transportTypeCallback.");
+ }
+ if (executor == null) {
+ throw new IllegalArgumentException("Must include a non-null Executor.");
+ }
+ throw new UnsupportedOperationException("getRegistrationTransportType is not"
+ + "supported.");
+ }
+
+
/**
* Registers an {@link AvailabilityCallback} with the system, which will provide RCS
* availability updates for the subscription specified.
diff --git a/telephony/java/android/telephony/ims/ImsReasonInfo.java b/telephony/java/android/telephony/ims/ImsReasonInfo.java
index 10251d7..663b09a 100644
--- a/telephony/java/android/telephony/ims/ImsReasonInfo.java
+++ b/telephony/java/android/telephony/ims/ImsReasonInfo.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -32,6 +33,7 @@
* @hide
*/
@SystemApi
+@TestApi
public final class ImsReasonInfo implements Parcelable {
/**
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index e6777c17..62bc2ae 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -17,6 +17,7 @@
package android.telephony.ims;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
@@ -90,6 +91,7 @@
* @hide
*/
@SystemApi
+@TestApi
public class ImsService extends Service {
private static final String LOG_TAG = "ImsService";
diff --git a/telephony/java/android/telephony/ims/ImsSsData.java b/telephony/java/android/telephony/ims/ImsSsData.java
index ec2ff6c..6b72859 100644
--- a/telephony/java/android/telephony/ims/ImsSsData.java
+++ b/telephony/java/android/telephony/ims/ImsSsData.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.Rlog;
@@ -35,6 +36,7 @@
* {@hide}
*/
@SystemApi
+@TestApi
public final class ImsSsData implements Parcelable {
private static final String TAG = ImsSsData.class.getCanonicalName();
diff --git a/telephony/java/android/telephony/ims/ImsSsInfo.java b/telephony/java/android/telephony/ims/ImsSsInfo.java
index be34f9d..77bd984 100644
--- a/telephony/java/android/telephony/ims/ImsSsInfo.java
+++ b/telephony/java/android/telephony/ims/ImsSsInfo.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -37,6 +38,7 @@
* @hide
*/
@SystemApi
+@TestApi
public final class ImsSsInfo implements Parcelable {
/**@hide*/
@@ -336,4 +338,31 @@
public @ClirInterrogationStatus int getClirInterrogationStatus() {
return mClirInterrogationStatus;
}
+
+ /**
+ * Parts of telephony still use the old {m,n} 3GPP definition, so convert to that format.
+ * @hide
+ */
+ public int[] getCompatArray(@ImsSsData.ServiceType int type) {
+ int[] result = new int[2];
+ // Convert ImsSsInfo into a form that telephony can read (as per 3GPP 27.007)
+ // CLIR (section 7.7)
+ if (type == ImsSsData.SS_CLIR) {
+ // Assume there will only be one ImsSsInfo.
+ // contains {"n","m"} parameters
+ result[0] = getClirOutgoingState();
+ result[1] = getClirInterrogationStatus();
+ return result;
+ }
+ // COLR 7.31
+ if (type == ImsSsData.SS_COLR) {
+ result[0] = getProvisionStatus();
+ }
+ // Facility Lock CLCK 7.4 (for call barring), CLIP 7.6, COLP 7.8, as well as any
+ // other result, just return the status for the "n" parameter and provisioning status for
+ // "m" as the default.
+ result[0] = getStatus();
+ result[1] = getProvisionStatus();
+ return result;
+ }
}
diff --git a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
index c1f059e..b7ab0a0 100644
--- a/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
+++ b/telephony/java/android/telephony/ims/ImsStreamMediaProfile.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -29,6 +30,7 @@
* @hide
*/
@SystemApi
+@TestApi
public final class ImsStreamMediaProfile implements Parcelable {
private static final String TAG = "ImsStreamMediaProfile";
diff --git a/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
index 1630368..f67f68e 100644
--- a/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
+++ b/telephony/java/android/telephony/ims/ImsSuppServiceNotification.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -31,6 +32,7 @@
* @hide
*/
@SystemApi
+@TestApi
public final class ImsSuppServiceNotification implements Parcelable {
private static final String TAG = "ImsSuppServiceNotification";
diff --git a/telephony/java/android/telephony/ims/ImsUtListener.java b/telephony/java/android/telephony/ims/ImsUtListener.java
index d50a0f7..bc124044 100644
--- a/telephony/java/android/telephony/ims/ImsUtListener.java
+++ b/telephony/java/android/telephony/ims/ImsUtListener.java
@@ -16,22 +16,55 @@
package android.telephony.ims;
+import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Bundle;
import android.os.RemoteException;
+import android.telephony.ims.stub.ImsUtImplBase;
import android.util.Log;
import com.android.ims.internal.IImsUtListener;
/**
- * Base implementation of the IMS UT listener interface, which implements stubs.
- * Override these methods to implement functionality.
+ * Listener interface used to receive network responses back from UT supplementary service queries
+ * made by the framework.
* @hide
*/
// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
// will break other implementations of ImsUt maintained by other ImsServices.
@SystemApi
+@TestApi
public class ImsUtListener {
+
+ /**
+ * The {@link Bundle} key for a Calling Line Identification Restriction (CLIR) response. The
+ * value will be an int[] with two values:
+ * int[0] contains the 'n' parameter from TS 27.007 7.7, which is the
+ * outgoing CLIR state. See {@link ImsSsInfo#CLIR_OUTGOING_DEFAULT},
+ * {@link ImsSsInfo#CLIR_OUTGOING_INVOCATION}, and {@link ImsSsInfo#CLIR_OUTGOING_SUPPRESSION};
+ * int[1] contains the 'm' parameter from TS 27.007 7.7, which is the CLIR interrogation status.
+ * See {@link ImsSsInfo#CLIR_STATUS_NOT_PROVISIONED},
+ * {@link ImsSsInfo#CLIR_STATUS_PROVISIONED_PERMANENT}, {@link ImsSsInfo#CLIR_STATUS_UNKNOWN},
+ * {@link ImsSsInfo#CLIR_STATUS_TEMPORARILY_RESTRICTED}, and
+ * {@link ImsSsInfo#CLIR_STATUS_TEMPORARILY_ALLOWED}.
+ * @deprecated Use {@link #onLineIdentificationSupplementaryServiceResponse(int, ImsSsInfo)}
+ * instead.
+ */
+ @Deprecated
+ public static final String BUNDLE_KEY_CLIR = "queryClir";
+
+ /**
+ * The {@link Bundle} key for a Calling Line Identification Presentation (CLIP), Connected Line
+ * Identification Presentation (COLP), or Connected Line Identification Restriction (COLR)
+ * response. The value will be an instance of {@link ImsSsInfo}, which contains the response to
+ * the query.
+ * @deprecated Use {@link #onLineIdentificationSupplementaryServiceResponse(int, ImsSsInfo)}
+ * instead.
+ */
+ @Deprecated
+ public static final String BUNDLE_KEY_SSINFO = "imsSsInfo";
+
private IImsUtListener mServiceInterface;
private static final String LOG_TAG = "ImsUtListener";
@@ -51,14 +84,54 @@
}
}
- public void onUtConfigurationQueried(int id, Bundle ssInfo) {
+ /**
+ * Notify the framework of a UT configuration response to a {@link ImsUtImplBase#queryClir()},
+ * {@link ImsUtImplBase#queryClip()}, {@link ImsUtImplBase#queryColp()}, or
+ * {@link ImsUtImplBase#queryColr()} query for the transaction ID specified. If the query fails,
+ * {@link #onUtConfigurationQueryFailed(int, ImsReasonInfo)} should be called.
+ * @param id The ID associated with this UT configuration transaction from the framework.
+ * @param configuration A {@link Bundle} containing the result of querying the UT configuration.
+ * Must contain {@link #BUNDLE_KEY_CLIR} if it is a response to
+ * {@link ImsUtImplBase#queryClir()} or
+ * {@link #BUNDLE_KEY_SSINFO} if it is a response to
+ * {@link ImsUtImplBase#queryClip()}, {@link ImsUtImplBase#queryColp()}, or
+ * {@link ImsUtImplBase#queryColr()}.
+ * @deprecated Use {@link #onLineIdentificationSupplementaryServiceResponse(int, ImsSsInfo)}
+ * instead.
+ */
+ @Deprecated
+ public void onUtConfigurationQueried(int id, Bundle configuration) {
try {
- mServiceInterface.utConfigurationQueried(null, id, ssInfo);
+ mServiceInterface.utConfigurationQueried(null, id, configuration);
} catch (RemoteException e) {
Log.w(LOG_TAG, "utConfigurationQueried: remote exception");
}
}
+ /**
+ * Notify the framework of a UT configuration response to a {@link ImsUtImplBase#queryClir()},
+ * {@link ImsUtImplBase#queryClip()}, {@link ImsUtImplBase#queryColp()}, or
+ * {@link ImsUtImplBase#queryColr()} query for the transaction ID specified. If the query fails,
+ * the framework should be notified via
+ * {@link #onUtConfigurationQueryFailed(int, ImsReasonInfo)}.
+ * @param id The ID associated with this UT configuration transaction from the framework.
+ * @param configuration An {@link ImsSsInfo} instance containing the configuration for the
+ * line identification supplementary service queried.
+ */
+ public void onLineIdentificationSupplementaryServiceResponse(int id,
+ @NonNull ImsSsInfo configuration) {
+ try {
+ mServiceInterface.lineIdentificationSupplementaryServiceResponse(id, configuration);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "onLineIdentificationSupplementaryServicesResponse: remote exception");
+ }
+ }
+
+ /**
+ * Notify the Framework of the line identification query failure.
+ * @param id The ID associated with the UT query transaction.
+ * @param error The query failure reason.
+ */
public void onUtConfigurationQueryFailed(int id, ImsReasonInfo error) {
try {
mServiceInterface.utConfigurationQueryFailed(null, id, error);
diff --git a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
index 1772401..270e693 100644
--- a/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
+++ b/telephony/java/android/telephony/ims/ImsVideoCallProvider.java
@@ -17,6 +17,7 @@
package android.telephony.ims;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.net.Uri;
import android.os.Handler;
@@ -36,6 +37,7 @@
* @hide
*/
@SystemApi
+@TestApi
public abstract class ImsVideoCallProvider {
private static final int MSG_SET_CALLBACK = 1;
private static final int MSG_SET_CAMERA = 2;
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index effdf48..e16085e 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -23,6 +23,7 @@
import android.annotation.RequiresPermission;
import android.annotation.StringDef;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.annotation.WorkerThread;
import android.content.Context;
import android.content.pm.IPackageManager;
@@ -59,6 +60,7 @@
* @hide
*/
@SystemApi
+@TestApi
public class ProvisioningManager {
/**@hide*/
diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java
new file mode 100644
index 0000000..99bb259
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RegistrationManager.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony.ims;
+
+import android.Manifest;
+import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.net.Uri;
+import android.os.Binder;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.ims.aidl.IImsRegistrationCallback;
+import android.telephony.ims.feature.ImsFeature;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.util.Log;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+
+/**
+ * Manages IMS Service registration state for associated {@link ImsFeature}s.
+ * @hide
+ */
+@SystemApi
+@TestApi
+public interface RegistrationManager {
+
+ /**
+ * @hide
+ */
+ // Defines the underlying radio technology type that we have registered for IMS over.
+ @IntDef(prefix = "REGISTRATION_STATE_",
+ value = {
+ REGISTRATION_STATE_NOT_REGISTERED,
+ REGISTRATION_STATE_REGISTERING,
+ REGISTRATION_STATE_REGISTERED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ImsRegistrationState {}
+
+ /**
+ * The IMS service is currently not registered to the carrier network.
+ */
+ int REGISTRATION_STATE_NOT_REGISTERED = 0;
+
+ /**
+ * The IMS service is currently in the process of registering to the carrier network.
+ */
+ int REGISTRATION_STATE_REGISTERING = 1;
+
+ /**
+ * The IMS service is currently registered to the carrier network.
+ */
+ int REGISTRATION_STATE_REGISTERED = 2;
+
+
+ /**@hide*/
+ // Translate ImsRegistrationImplBase API to new AccessNetworkConstant because WLAN
+ // and WWAN are more accurate constants.
+ Map<Integer, Integer> IMS_REG_TO_ACCESS_TYPE_MAP =
+ new HashMap<Integer, Integer>() {{
+ // Map NONE to -1 to make sure that we handle the REGISTRATION_TECH_NONE
+ // case, since it is defined.
+ put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE, -1);
+ put(ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+ put(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
+ AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
+ }};
+
+ /**
+ * Callback class for receiving IMS network Registration callback events.
+ * @see #registerImsRegistrationCallback(Executor, RegistrationCallback)
+ * @see #unregisterImsRegistrationCallback(RegistrationCallback)
+ */
+ class RegistrationCallback {
+
+ private static class RegistrationBinder extends IImsRegistrationCallback.Stub {
+
+ private final RegistrationCallback mLocalCallback;
+ private Executor mExecutor;
+
+ RegistrationBinder(RegistrationCallback localCallback) {
+ mLocalCallback = localCallback;
+ }
+
+ @Override
+ public void onRegistered(int imsRadioTech) {
+ if (mLocalCallback == null) return;
+
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(() ->
+ mLocalCallback.onRegistered(getAccessType(imsRadioTech))));
+ }
+
+ @Override
+ public void onRegistering(int imsRadioTech) {
+ if (mLocalCallback == null) return;
+
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(() ->
+ mLocalCallback.onRegistering(getAccessType(imsRadioTech))));
+ }
+
+ @Override
+ public void onDeregistered(ImsReasonInfo info) {
+ if (mLocalCallback == null) return;
+
+ Binder.withCleanCallingIdentity(() ->
+ mExecutor.execute(() -> mLocalCallback.onUnregistered(info)));
+ }
+
+ @Override
+ public void onTechnologyChangeFailed(int imsRadioTech, ImsReasonInfo info) {
+ if (mLocalCallback == null) return;
+
+ Binder.withCleanCallingIdentity(() ->
+ mExecutor.execute(() -> mLocalCallback.onTechnologyChangeFailed(
+ getAccessType(imsRadioTech), info)));
+ }
+
+ @Override
+ public void onSubscriberAssociatedUriChanged(Uri[] uris) {
+ if (mLocalCallback == null) return;
+
+ Binder.withCleanCallingIdentity(() ->
+ mExecutor.execute(() ->
+ mLocalCallback.onSubscriberAssociatedUriChanged(uris)));
+ }
+
+ private void setExecutor(Executor executor) {
+ mExecutor = executor;
+ }
+
+ private static int getAccessType(int regType) {
+ if (!RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.containsKey(regType)) {
+ Log.w("RegistrationManager", "RegistrationBinder - invalid regType returned: "
+ + regType);
+ return -1;
+ }
+ return RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(regType);
+ }
+ }
+
+ private final RegistrationBinder mBinder = new RegistrationBinder(this);
+
+ /**
+ * Notifies the framework when the IMS Provider is registered to the IMS network.
+ *
+ * @param imsTransportType the radio access technology.
+ */
+ public void onRegistered(@AccessNetworkConstants.TransportType int imsTransportType) {
+ }
+
+ /**
+ * Notifies the framework when the IMS Provider is trying to register the IMS network.
+ *
+ * @param imsTransportType the radio access technology.
+ */
+ public void onRegistering(@AccessNetworkConstants.TransportType int imsTransportType) {
+ }
+
+ /**
+ * Notifies the framework when the IMS Provider is deregistered from the IMS network.
+ *
+ * @param info the {@link ImsReasonInfo} associated with why registration was disconnected.
+ */
+ public void onUnregistered(@Nullable ImsReasonInfo info) {
+ }
+
+ /**
+ * A failure has occurred when trying to handover registration to another technology type.
+ *
+ * @param imsTransportType The transport type that has failed to handover registration to.
+ * @param info A {@link ImsReasonInfo} that identifies the reason for failure.
+ */
+ public void onTechnologyChangeFailed(
+ @AccessNetworkConstants.TransportType int imsTransportType,
+ @Nullable ImsReasonInfo info) {
+ }
+
+ /**
+ * Returns a list of subscriber {@link Uri}s associated with this IMS subscription when
+ * it changes. Per RFC3455, an associated URI is a URI that the service provider has
+ * allocated to a user for their own usage. A user's phone number is typically one of the
+ * associated URIs.
+ * @param uris new array of subscriber {@link Uri}s that are associated with this IMS
+ * subscription.
+ * @hide
+ */
+ public void onSubscriberAssociatedUriChanged(@Nullable Uri[] uris) {
+ }
+
+ /**@hide*/
+ public final IImsRegistrationCallback getBinder() {
+ return mBinder;
+ }
+
+ /**@hide*/
+ //Only exposed as public for compatibility with deprecated ImsManager APIs.
+ public void setExecutor(Executor executor) {
+ mBinder.setExecutor(executor);
+ }
+ }
+
+ /**
+ * Registers a {@link RegistrationCallback} with the system. Use
+ * {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed
+ * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up.
+ *
+ * When the callback is registered, it will initiate the callback c to be called with the
+ * current registration state.
+ *
+ * @param executor The executor the callback events should be run on.
+ * @param c The {@link RegistrationCallback} to be added.
+ * @see #unregisterImsRegistrationCallback(RegistrationCallback)
+ * @throws ImsException if the subscription associated with this callback is valid, but
+ * the {@link ImsService} associated with the subscription is not available. This can happen if
+ * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
+ * reason.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ void registerImsRegistrationCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull RegistrationCallback c) throws ImsException;
+
+ /**
+ * Removes an existing {@link RegistrationCallback}.
+ *
+ * When the subscription associated with this callback is removed (SIM removed, ESIM swap,
+ * etc...), this callback will automatically be removed. If this method is called for an
+ * inactive subscription, it will result in a no-op.
+ *
+ * @param c The {@link RegistrationCallback} to be removed.
+ * @see SubscriptionManager.OnSubscriptionsChangedListener
+ * @see #registerImsRegistrationCallback(Executor, RegistrationCallback)
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ void unregisterImsRegistrationCallback(@NonNull RegistrationCallback c);
+
+ /**
+ * Gets the registration state of the IMS service.
+ * @param executor The {@link Executor} that will be used to call the IMS registration state
+ * callback.
+ * @param stateCallback A callback called on the supplied {@link Executor} that will contain the
+ * registration state of the IMS service, which will be one of the
+ * following: {@link #REGISTRATION_STATE_NOT_REGISTERED},
+ * {@link #REGISTRATION_STATE_REGISTERING}, or
+ * {@link #REGISTRATION_STATE_REGISTERED}.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ void getRegistrationState(@NonNull @CallbackExecutor Executor executor,
+ @NonNull @ImsRegistrationState Consumer<Integer> stateCallback);
+
+ /**
+ * Gets the Transport Type associated with the current IMS registration.
+ * @param executor The {@link Executor} that will be used to call the transportTypeCallback.
+ * @param transportTypeCallback The transport type associated with the current IMS registration,
+ * which will be one of following:
+ * {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN},
+ * {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, or
+ * {@link AccessNetworkConstants#TRANSPORT_TYPE_INVALID}.
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ void getRegistrationTransportType(
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull @AccessNetworkConstants.TransportType Consumer<Integer> transportTypeCallback);
+}
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
index 976c2be..ae113f2 100644
--- a/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsUtListenerImplBase.java
@@ -18,12 +18,11 @@
import android.os.Bundle;
import android.os.RemoteException;
-
-import android.annotation.UnsupportedAppUsage;
import android.telephony.ims.ImsCallForwardInfo;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsSsData;
import android.telephony.ims.ImsSsInfo;
+
import com.android.ims.internal.IImsUt;
import com.android.ims.internal.IImsUtListener;
@@ -65,6 +64,13 @@
}
/**
+ * Notifies the result of a line identification supplementary service query.
+ */
+ @Override
+ public void lineIdentificationSupplementaryServiceResponse(int id, ImsSsInfo config) {
+ }
+
+ /**
* Notifies the status of the call barring supplementary service.
*/
@Override
diff --git a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
index 87a5094..1918bcb 100644
--- a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
+++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
@@ -18,6 +18,7 @@
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -33,6 +34,7 @@
* {@hide}
*/
@SystemApi
+@TestApi
public final class CapabilityChangeRequest implements Parcelable {
/**
diff --git a/telephony/java/android/telephony/ims/feature/ImsFeature.java b/telephony/java/android/telephony/ims/feature/ImsFeature.java
index 3562880..72390d0 100644
--- a/telephony/java/android/telephony/ims/feature/ImsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/ImsFeature.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.content.Context;
import android.os.IInterface;
import android.os.RemoteCallbackList;
@@ -43,6 +44,7 @@
* @hide
*/
@SystemApi
+@TestApi
public abstract class ImsFeature {
private static final String LOG_TAG = "ImsFeature";
@@ -212,6 +214,7 @@
// Not Actually deprecated, but we need to remove it from the @SystemApi surface.
@Deprecated
@SystemApi // SystemApi only because it was leaked through type usage in a previous release.
+ @TestApi
public static class Capabilities {
/** @deprecated Use getters and accessors instead. */
// Not actually deprecated, but we need to remove it from the @SystemApi surface eventually.
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index ceb4704..56c8771 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -20,6 +20,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Bundle;
import android.os.Message;
import android.os.RemoteException;
@@ -54,6 +55,7 @@
* @hide
*/
@SystemApi
+@TestApi
public class MmTelFeature extends ImsFeature {
private static final String LOG_TAG = "MmTelFeature";
@@ -362,6 +364,25 @@
@Retention(RetentionPolicy.SOURCE)
public @interface ProcessCallResult {}
+ /**
+ * If the flag is present and true, it indicates that the incoming call is for USSD.
+ * <p>
+ * This is an optional boolean flag.
+ */
+ public static final String EXTRA_IS_USSD = "android.telephony.ims.feature.extra.IS_USSD";
+
+ /**
+ * If this flag is present and true, this call is marked as an unknown dialing call instead
+ * of an incoming call. An example of such a call is a call that is originated by sending
+ * commands (like AT commands) directly to the modem without Android involvement or dialing
+ * calls appearing over IMS when the modem does a silent redial from circuit-switched to IMS in
+ * certain situations.
+ * <p>
+ * This is an optional boolean flag.
+ */
+ public static final String EXTRA_IS_UNKNOWN_CALL =
+ "android.telephony.ims.feature.extra.IS_UNKNOWN_CALL";
+
private IImsMmTelListener mListener;
/**
@@ -410,6 +431,8 @@
/**
* Notify the framework of an incoming call.
* @param c The {@link ImsCallSessionImplBase} of the new incoming call.
+ * @param extras A bundle containing extra parameters related to the call. See
+ * {@link #EXTRA_IS_UNKNOWN_CALL} and {@link #EXTRA_IS_USSD} above.
*/
public final void notifyIncomingCall(@NonNull ImsCallSessionImplBase c,
@NonNull Bundle extras) {
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index f69b434..119f890 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -20,6 +20,7 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.net.Uri;
import android.os.Binder;
import android.os.RemoteException;
@@ -49,6 +50,7 @@
* @hide
*/
@SystemApi
+@TestApi
public class RcsFeature extends ImsFeature {
private static final String LOG_TAG = "RcsFeature";
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index da6a7a6..f4367da 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -17,19 +17,19 @@
package android.telephony.ims.stub;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Message;
import android.os.RemoteException;
-import android.telephony.ims.ImsCallSessionListener;
-import android.telephony.ims.aidl.IImsCallSessionListener;
-
import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsCallSession;
+import android.telephony.ims.ImsCallSessionListener;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsStreamMediaProfile;
-import android.telephony.ims.ImsCallSession;
+import android.telephony.ims.ImsVideoCallProvider;
+import android.telephony.ims.aidl.IImsCallSessionListener;
+
import com.android.ims.internal.IImsCallSession;
import com.android.ims.internal.IImsVideoCallProvider;
-import android.telephony.ims.ImsVideoCallProvider;
-
/**
* Base implementation of IImsCallSession, which implements stub versions of the methods available.
*
@@ -38,6 +38,7 @@
* @hide
*/
@SystemApi
+@TestApi
// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
// will break other implementations of ImsCallSession maintained by other ImsServices.
public class ImsCallSessionImplBase implements AutoCloseable {
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index 3e135cc..4c0de7f 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -18,6 +18,7 @@
import android.annotation.IntDef;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.content.Context;
import android.os.PersistableBundle;
import android.os.RemoteCallbackList;
@@ -48,6 +49,7 @@
* @hide
*/
@SystemApi
+@TestApi
public class ImsConfigImplBase {
private static final String TAG = "ImsConfigImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
index 06c35ea..4a3a2ea 100644
--- a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
@@ -17,6 +17,7 @@
package android.telephony.ims.stub;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.RemoteException;
import android.util.Log;
@@ -33,6 +34,7 @@
* @hide
*/
@SystemApi
+@TestApi
public class ImsEcbmImplBase {
private static final String TAG = "ImsEcbmImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
index cd9ebbf..4e7307e 100644
--- a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
+++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.ims.feature.ImsFeature;
@@ -35,6 +36,7 @@
* @hide
*/
@SystemApi
+@TestApi
public final class ImsFeatureConfiguration implements Parcelable {
public static final class FeatureSlotPair {
diff --git a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
index ce2d89a..0ae5bba 100644
--- a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
@@ -17,10 +17,11 @@
package android.telephony.ims.stub;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.RemoteException;
+import android.telephony.ims.ImsExternalCallState;
import android.util.Log;
-import android.telephony.ims.ImsExternalCallState;
import com.android.ims.internal.IImsExternalCallStateListener;
import com.android.ims.internal.IImsMultiEndpoint;
@@ -37,6 +38,7 @@
* @hide
*/
@SystemApi
+@TestApi
public class ImsMultiEndpointImplBase {
private static final String TAG = "MultiEndpointImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index a08e031..c0f16e5 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -18,10 +18,12 @@
import android.annotation.IntDef;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.net.Uri;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.RegistrationManager;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.util.Log;
@@ -37,6 +39,7 @@
* @hide
*/
@SystemApi
+@TestApi
public class ImsRegistrationImplBase {
private static final String LOG_TAG = "ImsRegistrationImplBase";
@@ -72,9 +75,6 @@
// with NOT_REGISTERED in the case where the ImsService has not updated the registration state
// yet.
private static final int REGISTRATION_STATE_UNKNOWN = -1;
- private static final int REGISTRATION_STATE_NOT_REGISTERED = 0;
- private static final int REGISTRATION_STATE_REGISTERING = 1;
- private static final int REGISTRATION_STATE_REGISTERED = 2;
private final IImsRegistration mBinder = new IImsRegistration.Stub() {
@@ -128,7 +128,7 @@
* {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}.
*/
public final void onRegistered(@ImsRegistrationTech int imsRadioTech) {
- updateToState(imsRadioTech, REGISTRATION_STATE_REGISTERED);
+ updateToState(imsRadioTech, RegistrationManager.REGISTRATION_STATE_REGISTERED);
mCallbacks.broadcast((c) -> {
try {
c.onRegistered(imsRadioTech);
@@ -146,7 +146,7 @@
* {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}.
*/
public final void onRegistering(@ImsRegistrationTech int imsRadioTech) {
- updateToState(imsRadioTech, REGISTRATION_STATE_REGISTERING);
+ updateToState(imsRadioTech, RegistrationManager.REGISTRATION_STATE_REGISTERING);
mCallbacks.broadcast((c) -> {
try {
c.onRegistering(imsRadioTech);
@@ -230,7 +230,8 @@
private void updateToDisconnectedState(ImsReasonInfo info) {
synchronized (mLock) {
- updateToState(REGISTRATION_TECH_NONE, REGISTRATION_STATE_NOT_REGISTERED);
+ updateToState(REGISTRATION_TECH_NONE,
+ RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED);
if (info != null) {
mLastDisconnectCause = info;
} else {
@@ -264,15 +265,15 @@
disconnectInfo = mLastDisconnectCause;
}
switch (state) {
- case REGISTRATION_STATE_NOT_REGISTERED: {
+ case RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED: {
c.onDeregistered(disconnectInfo);
break;
}
- case REGISTRATION_STATE_REGISTERING: {
+ case RegistrationManager.REGISTRATION_STATE_REGISTERING: {
c.onRegistering(getConnectionType());
break;
}
- case REGISTRATION_STATE_REGISTERED: {
+ case RegistrationManager.REGISTRATION_STATE_REGISTERED: {
c.onRegistered(getConnectionType());
break;
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
index 36ece95..ce9a73a 100644
--- a/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsSmsImplBase.java
@@ -19,6 +19,7 @@
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.RemoteException;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
@@ -37,6 +38,7 @@
* @hide
*/
@SystemApi
+@TestApi
public class ImsSmsImplBase {
private static final String LOG_TAG = "SmsImplBase";
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
index fcd7faf..feac3c2 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
@@ -17,6 +17,7 @@
package android.telephony.ims.stub;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.ims.ImsUtListener;
@@ -33,6 +34,7 @@
// DO NOT remove or change the existing APIs, only add new ones to this Base implementation or you
// will break other implementations of ImsUt maintained by other ImsServices.
@SystemApi
+@TestApi
public class ImsUtImplBase {
private IImsUt.Stub mServiceImpl = new IImsUt.Stub() {
diff --git a/telephony/java/com/android/ims/internal/IImsUtListener.aidl b/telephony/java/com/android/ims/internal/IImsUtListener.aidl
index fcb9fb1..9a12cee 100644
--- a/telephony/java/com/android/ims/internal/IImsUtListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsUtListener.aidl
@@ -44,6 +44,7 @@
@UnsupportedAppUsage
void utConfigurationQueryFailed(in IImsUt ut, int id, in ImsReasonInfo error);
+ void lineIdentificationSupplementaryServiceResponse(int id, in ImsSsInfo config);
/**
* Notifies the status of the call barring supplementary service.
*/
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index f3a335d..91aa3ce 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -574,4 +574,23 @@
* @param destAddress the destination address to test for possible short code
*/
int checkSmsShortCodeDestination(int subId, String callingApk, String destAddress, String countryIso);
+
+ /**
+ * Gets the SMSC address from (U)SIM.
+ *
+ * @param subId the subscription Id.
+ * @param callingPackage the package name of the calling app.
+ * @return the SMSC address string, null if failed.
+ */
+ String getSmscAddressFromIccEfForSubscriber(int subId, String callingPackage);
+
+ /**
+ * Sets the SMSC address on (U)SIM.
+ *
+ * @param smsc the SMSC address string.
+ * @param subId the subscription Id.
+ * @param callingPackage the package name of the calling app.
+ * @return true for success, false otherwise.
+ */
+ boolean setSmscAddressOnIccEfForSubscriber(String smsc, int subId, String callingPackage);
}
diff --git a/telephony/java/com/android/internal/telephony/ISmsImplBase.java b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
index 2096325..d9d4b60 100644
--- a/telephony/java/com/android/internal/telephony/ISmsImplBase.java
+++ b/telephony/java/com/android/internal/telephony/ISmsImplBase.java
@@ -201,4 +201,15 @@
int subid, String callingApk, String destAddress, String countryIso) {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public String getSmscAddressFromIccEfForSubscriber(int subId, String callingPackage) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean setSmscAddressOnIccEfForSubscriber(
+ String smsc, int subId, String callingPackage) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index f79a5c6..c6c9f34 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -295,7 +295,7 @@
*/
boolean isDataConnectivityPossible(int subId);
- Bundle getCellLocation(String callingPkg);
+ Bundle getCellLocation(String callingPkg, String callingFeatureId);
/**
* Returns the ISO country code equivalent of the current registered
@@ -307,7 +307,7 @@
/**
* Returns the neighboring cell information of the device.
*/
- List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg);
+ List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg, String callingFeatureId);
@UnsupportedAppUsage
int getCallState();
@@ -556,13 +556,14 @@
/**
* Returns all observed cell information of the device.
*/
- List<CellInfo> getAllCellInfo(String callingPkg);
+ List<CellInfo> getAllCellInfo(String callingPkg, String callingFeatureId);
/**
* Request a cell information update for the specified subscription,
* reported via the CellInfoCallback.
*/
- void requestCellInfoUpdate(int subId, in ICellInfoCallback cb, String callingPkg);
+ void requestCellInfoUpdate(int subId, in ICellInfoCallback cb, String callingPkg,
+ String callingFeatureId);
/**
* Request a cell information update for the specified subscription,
@@ -570,8 +571,8 @@
*
* @param workSource the requestor to whom the power consumption for this should be attributed.
*/
- void requestCellInfoUpdateWithWorkSource(
- int subId, in ICellInfoCallback cb, in String callingPkg, in WorkSource ws);
+ void requestCellInfoUpdateWithWorkSource(int subId, in ICellInfoCallback cb,
+ in String callingPkg, String callingFeatureId, in WorkSource ws);
/**
* Sets minimum time in milli-seconds between onCellInfoChanged
@@ -867,6 +868,11 @@
String getImsService(int slotId, boolean isCarrierImsService);
/**
+ * Get the MmTelFeature state attached to this subscription id.
+ */
+ void getImsMmTelFeatureState(int subId, IIntegerConsumer callback);
+
+ /**
* Set the network selection mode to automatic.
*
* @param subId the id of the subscription to update.
@@ -877,9 +883,12 @@
* Perform a radio scan and return the list of avialble networks.
*
* @param subId the id of the subscription.
+ * @param callingPackage the calling package
+ * @param callingFeatureId The feature in the package
* @return CellNetworkScanResult containing status of scan and networks.
*/
- CellNetworkScanResult getCellNetworkScanResults(int subId, String callingPackage);
+ CellNetworkScanResult getCellNetworkScanResults(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Perform a radio network scan and return the id of this scan.
@@ -889,10 +898,11 @@
* @param messenger Callback messages will be sent using this messenger.
* @param binder the binder object instantiated in TelephonyManager.
* @param callingPackage the calling package
+ * @param callingFeatureId The feature in the package
* @return An id for this scan.
*/
int requestNetworkScan(int subId, in NetworkScanRequest request, in Messenger messenger,
- in IBinder binder, in String callingPackage);
+ in IBinder binder, in String callingPackage, String callingFeatureId);
/**
* Stop an existing radio network scan.
@@ -1308,6 +1318,12 @@
int getSubIdForPhoneAccount(in PhoneAccount phoneAccount);
/**
+ * Returns the subscription ID associated with the specified PhoneAccountHandle.
+ */
+ int getSubIdForPhoneAccountHandle(in PhoneAccountHandle phoneAccountHandle,
+ String callingPackage);
+
+ /**
* Returns the PhoneAccountHandle associated with a subscription ID.
*/
PhoneAccountHandle getPhoneAccountHandleForSubscriptionId(int subscriptionId);
@@ -1335,9 +1351,11 @@
* Get the service state on specified subscription
* @param subId Subscription id
* @param callingPackage The package making the call
+ * @param callingFeatureId The feature in the package
* @return Service state on specified subscription.
*/
- ServiceState getServiceStateForSubscriber(int subId, String callingPackage);
+ ServiceState getServiceStateForSubscriber(int subId, String callingPackage,
+ String callingFeatureId);
/**
* Returns the URI for the per-account voicemail ringtone set in Phone settings.
@@ -1795,6 +1813,16 @@
void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback c);
/**
+ * Get the IMS service registration state for the MmTelFeature associated with this sub id.
+ */
+ void getImsMmTelRegistrationState(int subId, IIntegerConsumer consumer);
+
+ /**
+ * Get the transport type for the IMS service registration state.
+ */
+ void getImsMmTelRegistrationTransportType(int subId, IIntegerConsumer consumer);
+
+ /**
* Adds an IMS MmTel capabilities callback for the subscription specified.
*/
void registerMmTelCapabilityCallback(int subId, IImsCapabilityCallback c);
@@ -1815,6 +1843,12 @@
boolean isAvailable(int subId, int capability, int regTech);
/**
+ * Return whether or not the MmTel capability is supported for the requested transport type.
+ */
+ void isMmTelCapabilitySupported(int subId, IIntegerConsumer callback, int capability,
+ int transportType);
+
+ /**
* Returns true if the user's setting for 4G LTE is enabled, for the subscription specified.
*/
boolean isAdvancedCallingSettingEnabled(int subId);
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
index c3d490a..5766287 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmSmsCbMessage.java
@@ -25,17 +25,17 @@
import android.annotation.NonNull;
import android.content.Context;
import android.content.res.Resources;
+import android.telephony.CbGeoUtils;
+import android.telephony.CbGeoUtils.Circle;
+import android.telephony.CbGeoUtils.Geometry;
+import android.telephony.CbGeoUtils.LatLng;
+import android.telephony.CbGeoUtils.Polygon;
import android.telephony.SmsCbLocation;
import android.telephony.SmsCbMessage;
import android.util.Pair;
import android.util.Slog;
import com.android.internal.R;
-import com.android.internal.telephony.CbGeoUtils;
-import com.android.internal.telephony.CbGeoUtils.Circle;
-import com.android.internal.telephony.CbGeoUtils.Geometry;
-import com.android.internal.telephony.CbGeoUtils.LatLng;
-import com.android.internal.telephony.CbGeoUtils.Polygon;
import com.android.internal.telephony.GsmAlphabet;
import com.android.internal.telephony.SmsConstants;
import com.android.internal.telephony.gsm.GsmSmsCbMessage.GeoFencingTriggerMessage.CellBroadcastIdentity;
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index 81b1e49..0b5d446 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -19,8 +19,14 @@
java_sdk_library {
name: "android.test.mock",
- srcs: ["src/**/*.java"],
- api_srcs: [":framework-all-sources"],
+ srcs: [
+ "src/**/*.java",
+ // Note: Below are NOT APIs of this library. We only take APIs under
+ // the android.test.mock package. They however provide private APIs that
+ // android.test.mock APIs references to.
+ ":framework-core-sources-for-test-mock",
+ ":framework_native_aidl",
+ ],
libs: ["framework-all"],
api_packages: [
diff --git a/test-mock/src/android/test/mock/MockContentProvider.java b/test-mock/src/android/test/mock/MockContentProvider.java
index 4d8c7d9..9d3e120 100644
--- a/test-mock/src/android/test/mock/MockContentProvider.java
+++ b/test-mock/src/android/test/mock/MockContentProvider.java
@@ -56,21 +56,22 @@
*/
private class InversionIContentProvider implements IContentProvider {
@Override
- public ContentProviderResult[] applyBatch(String callingPackage, String authority,
+ public ContentProviderResult[] applyBatch(String callingPackage,
+ @Nullable String featureId, String authority,
ArrayList<ContentProviderOperation> operations)
throws RemoteException, OperationApplicationException {
return MockContentProvider.this.applyBatch(authority, operations);
}
@Override
- public int bulkInsert(String callingPackage, Uri url, ContentValues[] initialValues)
- throws RemoteException {
+ public int bulkInsert(String callingPackage, @Nullable String featureId, Uri url,
+ ContentValues[] initialValues) throws RemoteException {
return MockContentProvider.this.bulkInsert(url, initialValues);
}
@Override
- public int delete(String callingPackage, Uri url, String selection, String[] selectionArgs)
- throws RemoteException {
+ public int delete(String callingPackage, @Nullable String featureId, Uri url,
+ String selection, String[] selectionArgs) throws RemoteException {
return MockContentProvider.this.delete(url, selection, selectionArgs);
}
@@ -80,42 +81,42 @@
}
@Override
- public Uri insert(String callingPackage, Uri url, ContentValues initialValues)
- throws RemoteException {
+ public Uri insert(String callingPackage, @Nullable String featureId, Uri url,
+ ContentValues initialValues) throws RemoteException {
return MockContentProvider.this.insert(url, initialValues);
}
@Override
- public AssetFileDescriptor openAssetFile(
- String callingPackage, Uri url, String mode, ICancellationSignal signal)
+ public AssetFileDescriptor openAssetFile(String callingPackage,
+ @Nullable String featureId, Uri url, String mode, ICancellationSignal signal)
throws RemoteException, FileNotFoundException {
return MockContentProvider.this.openAssetFile(url, mode);
}
@Override
- public ParcelFileDescriptor openFile(
- String callingPackage, Uri url, String mode, ICancellationSignal signal,
- IBinder callerToken) throws RemoteException, FileNotFoundException {
+ public ParcelFileDescriptor openFile(String callingPackage, @Nullable String featureId,
+ Uri url, String mode, ICancellationSignal signal, IBinder callerToken)
+ throws RemoteException, FileNotFoundException {
return MockContentProvider.this.openFile(url, mode);
}
@Override
- public Cursor query(String callingPackage, Uri url, @Nullable String[] projection,
- @Nullable Bundle queryArgs,
- @Nullable ICancellationSignal cancellationSignal)
- throws RemoteException {
+ public Cursor query(String callingPackage, @Nullable String featureId, Uri url,
+ @Nullable String[] projection, @Nullable Bundle queryArgs,
+ @Nullable ICancellationSignal cancellationSignal) throws RemoteException {
return MockContentProvider.this.query(url, projection, queryArgs, null);
}
@Override
- public int update(String callingPackage, Uri url, ContentValues values, String selection,
- String[] selectionArgs) throws RemoteException {
+ public int update(String callingPackage, @Nullable String featureId, Uri url,
+ ContentValues values, String selection, String[] selectionArgs)
+ throws RemoteException {
return MockContentProvider.this.update(url, values, selection, selectionArgs);
}
@Override
- public Bundle call(String callingPackage, String authority, String method, String request,
- Bundle args) throws RemoteException {
+ public Bundle call(String callingPackage, @Nullable String featureId, String authority,
+ String method, String request, Bundle args) throws RemoteException {
return MockContentProvider.this.call(authority, method, request, args);
}
@@ -130,9 +131,9 @@
}
@Override
- public AssetFileDescriptor openTypedAssetFile(String callingPackage, Uri url,
- String mimeType, Bundle opts, ICancellationSignal signal)
- throws RemoteException, FileNotFoundException {
+ public AssetFileDescriptor openTypedAssetFile(String callingPackage,
+ @Nullable String featureId, Uri url, String mimeType, Bundle opts,
+ ICancellationSignal signal) throws RemoteException, FileNotFoundException {
return MockContentProvider.this.openTypedAssetFile(url, mimeType, opts);
}
@@ -142,23 +143,26 @@
}
@Override
- public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException {
+ public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri)
+ throws RemoteException {
return MockContentProvider.this.canonicalize(uri);
}
@Override
- public Uri uncanonicalize(String callingPkg, Uri uri) throws RemoteException {
+ public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri)
+ throws RemoteException {
return MockContentProvider.this.uncanonicalize(uri);
}
@Override
- public boolean refresh(String callingPkg, Uri url, Bundle args,
- ICancellationSignal cancellationSignal) throws RemoteException {
+ public boolean refresh(String callingPkg, @Nullable String featureId, Uri url,
+ Bundle args, ICancellationSignal cancellationSignal) throws RemoteException {
return MockContentProvider.this.refresh(url, args);
}
@Override
- public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags) {
+ public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri,
+ int uid, int modeFlags) {
return MockContentProvider.this.checkUriPermission(uri, uid, modeFlags);
}
}
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index 5053cee..1de6260 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -463,6 +463,13 @@
}
@Override
+ public void sendOrderedBroadcast(Intent intent, String receiverPermission,
+ String receiverAppOp, BroadcastReceiver resultReceiver, Handler scheduler,
+ int initialCode, String initialData, Bundle initialExtras) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public void sendStickyBroadcast(Intent intent) {
throw new UnsupportedOperationException();
}
diff --git a/test-mock/src/android/test/mock/MockIContentProvider.java b/test-mock/src/android/test/mock/MockIContentProvider.java
index b072d74..e512b52 100644
--- a/test-mock/src/android/test/mock/MockIContentProvider.java
+++ b/test-mock/src/android/test/mock/MockIContentProvider.java
@@ -16,14 +16,12 @@
package android.test.mock;
-import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentValues;
import android.content.EntityIterator;
import android.content.IContentProvider;
-import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
@@ -45,14 +43,15 @@
*/
public class MockIContentProvider implements IContentProvider {
@Override
- public int bulkInsert(String callingPackage, Uri url, ContentValues[] initialValues) {
+ public int bulkInsert(String callingPackage, @Nullable String featureId, Uri url,
+ ContentValues[] initialValues) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
@SuppressWarnings("unused")
- public int delete(String callingPackage, Uri url, String selection, String[] selectionArgs)
- throws RemoteException {
+ public int delete(String callingPackage, @Nullable String featureId, Uri url,
+ String selection, String[] selectionArgs) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@@ -63,33 +62,33 @@
@Override
@SuppressWarnings("unused")
- public Uri insert(String callingPackage, Uri url, ContentValues initialValues)
- throws RemoteException {
+ public Uri insert(String callingPackage, @Nullable String featureId, Uri url,
+ ContentValues initialValues) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
- public ParcelFileDescriptor openFile(
- String callingPackage, Uri url, String mode, ICancellationSignal signal,
- IBinder callerToken) {
+ public ParcelFileDescriptor openFile(String callingPackage, @Nullable String featureId,
+ Uri url, String mode, ICancellationSignal signal, IBinder callerToken) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
- public AssetFileDescriptor openAssetFile(
- String callingPackage, Uri uri, String mode, ICancellationSignal signal) {
+ public AssetFileDescriptor openAssetFile(String callingPackage, @Nullable String featureId,
+ Uri uri, String mode, ICancellationSignal signal) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
- public ContentProviderResult[] applyBatch(String callingPackage, String authority,
- ArrayList<ContentProviderOperation> operations) {
+ public ContentProviderResult[] applyBatch(String callingPackage, @Nullable String featureId,
+ String authority, ArrayList<ContentProviderOperation> operations) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
- public Cursor query(String callingPackage, Uri url, @Nullable String[] projection,
- @Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal) {
+ public Cursor query(String callingPackage, @Nullable String featureId, Uri url,
+ @Nullable String[] projection, @Nullable Bundle queryArgs,
+ @Nullable ICancellationSignal cancellationSignal) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@@ -99,14 +98,14 @@
}
@Override
- public int update(String callingPackage, Uri url, ContentValues values, String selection,
- String[] selectionArgs) throws RemoteException {
+ public int update(String callingPackage, @Nullable String featureId, Uri url,
+ ContentValues values, String selection, String[] selectionArgs) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
- public Bundle call(String callingPackage, String authority, String method, String request,
- Bundle args) throws RemoteException {
+ public Bundle call(String callingPackage, @Nullable String featureId, String authority,
+ String method, String request, Bundle args) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@@ -121,8 +120,9 @@
}
@Override
- public AssetFileDescriptor openTypedAssetFile(String callingPackage, Uri url, String mimeType,
- Bundle opts, ICancellationSignal signal) throws RemoteException, FileNotFoundException {
+ public AssetFileDescriptor openTypedAssetFile(String callingPackage,
+ @Nullable String featureId, Uri url, String mimeType, Bundle opts,
+ ICancellationSignal signal) throws RemoteException, FileNotFoundException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@@ -132,24 +132,27 @@
}
@Override
- public Uri canonicalize(String callingPkg, Uri uri) throws RemoteException {
+ public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri)
+ throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
- public Uri uncanonicalize(String callingPkg, Uri uri) throws RemoteException {
+ public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri)
+ throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
- public boolean refresh(String callingPkg, Uri url, Bundle args,
+ public boolean refresh(String callingPkg, @Nullable String featureId, Uri url, Bundle args,
ICancellationSignal cancellationSignal) throws RemoteException {
throw new UnsupportedOperationException("unimplemented mock method");
}
/** {@hide} */
@Override
- public int checkUriPermission(String callingPkg, Uri uri, int uid, int modeFlags) {
+ public int checkUriPermission(String callingPkg, @Nullable String featureId, Uri uri, int uid,
+ int modeFlags) {
throw new UnsupportedOperationException("unimplemented mock method call");
}
}
diff --git a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
index 81937e6..74aaec1 100644
--- a/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
+++ b/tests/BootImageProfileTest/src/com/android/bootimageprofile/BootImageProfileTest.java
@@ -94,6 +94,8 @@
boolean sawServices = false;
for (String line : res.split("\n")) {
if (line.contains("framework.jar")) {
+ sawFramework = true; // Legacy
+ } else if (line.contains("framework-minus-apex.jar")) {
sawFramework = true;
} else if (line.contains("services.jar")) {
sawServices = true;
@@ -106,13 +108,18 @@
// Test the profile contents contain common methods for core-oj that would normally be AOT
// compiled.
res = mTestDevice.executeShellCommand("profman --dump-classes-and-methods --profile-file="
- + SYSTEM_SERVER_PROFILE + " --apk=/apex/com.android.art/javalib/core-oj.jar");
+ + SYSTEM_SERVER_PROFILE + " --apk=/apex/com.android.art/javalib/core-oj.jar"
+ + " --apk=/system/framework/services.jar");
boolean sawObjectInit = false;
+ boolean sawPmInit = false;
for (String line : res.split("\n")) {
if (line.contains("Ljava/lang/Object;-><init>()V")) {
sawObjectInit = true;
+ } else if (line.contains("Lcom/android/server/pm/PackageManagerService;-><init>")) {
+ sawPmInit = true;
}
}
assertTrue("Did not see Object.<init> in " + res, sawObjectInit);
+ assertTrue("Did not see PackageManagerService.<init> in " + res, sawPmInit);
}
}
diff --git a/tests/Codegen/runTest.sh b/tests/Codegen/runTest.sh
index 929f122..31ab6d2 100755
--- a/tests/Codegen/runTest.sh
+++ b/tests/Codegen/runTest.sh
@@ -17,6 +17,7 @@
header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java && \
header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java && \
header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java && \
+ header_and_eval codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java && \
(
cd $ANDROID_BUILD_TOP &&
header_and_eval mmma -j16 frameworks/base/tests/Codegen && \
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
index 325c1c0..176c7a0 100644
--- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java
@@ -32,7 +32,7 @@
- // Code below generated by codegen v1.0.9.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -98,11 +98,15 @@
};
@DataClass.Generated(
- time = 1571258914826L,
- codegenVersion = "1.0.9",
+ time = 1573006405823L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassBase.java",
inputSignatures = "private int mBaseData\nclass HierrarchicalDataClassBase extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genSetters=true)")
@Deprecated
private void __metadata() {}
+
+ //@formatter:on
+ // End of generated code
+
}
diff --git a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
index 6c92009..e348c77 100644
--- a/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
+++ b/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java
@@ -46,7 +46,7 @@
- // Code below generated by codegen v1.0.9.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -120,11 +120,15 @@
};
@DataClass.Generated(
- time = 1571258915848L,
- codegenVersion = "1.0.9",
+ time = 1573006406833L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/HierrarchicalDataClassChild.java",
inputSignatures = "private @android.annotation.NonNull java.lang.String mChildData\nclass HierrarchicalDataClassChild extends com.android.codegentest.HierrarchicalDataClassBase implements []\n@com.android.internal.util.DataClass(genParcelable=true, genConstructor=false, genSetters=true)")
@Deprecated
private void __metadata() {}
+
+ //@formatter:on
+ // End of generated code
+
}
diff --git a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
index 36def8a..112d3df 100644
--- a/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java
@@ -19,6 +19,7 @@
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.ArrayMap;
import android.util.SparseArray;
import android.util.SparseIntArray;
@@ -52,7 +53,8 @@
- // Code below generated by codegen v1.0.9.
+
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -361,7 +363,7 @@
}
/** Builds the instance. This builder should not be touched after calling this! */
- public ParcelAllTheThingsDataClass build() {
+ public @NonNull ParcelAllTheThingsDataClass build() {
checkNotUsed();
mBuilderFieldsSet |= 0x100; // Mark builder used
@@ -410,11 +412,15 @@
}
@DataClass.Generated(
- time = 1571258913802L,
- codegenVersion = "1.0.9",
+ time = 1573006404728L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/ParcelAllTheThingsDataClass.java",
inputSignatures = " @android.annotation.NonNull java.lang.String[] mStringArray\n @android.annotation.NonNull int[] mIntArray\n @android.annotation.NonNull java.util.List<java.lang.String> mStringList\n @android.annotation.NonNull java.util.Map<java.lang.String,com.android.codegentest.SampleWithCustomBuilder> mMap\n @android.annotation.NonNull java.util.Map<java.lang.String,java.lang.String> mStringMap\n @android.annotation.NonNull android.util.SparseArray<com.android.codegentest.SampleWithCustomBuilder> mSparseArray\n @android.annotation.NonNull android.util.SparseIntArray mSparseIntArray\n @java.lang.SuppressWarnings({\"WeakerAccess\"}) @android.annotation.Nullable java.lang.Boolean mNullableBoolean\nclass ParcelAllTheThingsDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)")
@Deprecated
private void __metadata() {}
+
+ //@formatter:on
+ // End of generated code
+
}
diff --git a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
index c444d61..0fdcf59 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleDataClass.java
@@ -342,7 +342,7 @@
- // Code below generated by codegen v1.0.9.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -1430,7 +1430,7 @@
*/
@SuppressWarnings("WeakerAccess")
@DataClass.Generated.Member
- public static class Builder {
+ public static final class Builder {
private int mNum;
private int mNum2;
@@ -1793,7 +1793,7 @@
}
/** Builds the instance. This builder should not be touched after calling this! */
- public SampleDataClass build() {
+ public @NonNull SampleDataClass build() {
checkNotUsed();
mBuilderFieldsSet |= 0x100000; // Mark builder used
@@ -1872,11 +1872,15 @@
}
@DataClass.Generated(
- time = 1571258911688L,
- codegenVersion = "1.0.9",
+ time = 1573006402566L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleDataClass.java",
inputSignatures = "public static final java.lang.String STATE_NAME_UNDEFINED\npublic static final java.lang.String STATE_NAME_ON\npublic static final java.lang.String STATE_NAME_OFF\npublic static final int STATE_UNDEFINED\npublic static final int STATE_ON\npublic static final int STATE_OFF\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @com.android.codegentest.SampleDataClass.RequestFlags int FLAG_AUGMENTED_REQUEST\nprivate int mNum\nprivate int mNum2\nprivate int mNum4\nprivate @android.annotation.Nullable java.lang.String mName\nprivate @android.annotation.NonNull java.lang.String mName2\nprivate @android.annotation.NonNull java.lang.String mName4\nprivate @android.annotation.Nullable android.view.accessibility.AccessibilityNodeInfo mOtherParcelable\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.codegentest.MyDateParcelling.class) @android.annotation.NonNull java.util.Date mDate\nprivate @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForPattern.class) @android.annotation.NonNull java.util.regex.Pattern mPattern\nprivate @android.annotation.NonNull java.util.List<android.net.LinkAddress> mLinkAddresses2\nprivate @com.android.internal.util.DataClass.PluralOf(\"linkAddress\") @android.annotation.NonNull java.util.ArrayList<android.net.LinkAddress> mLinkAddresses\nprivate @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses4\nprivate @com.android.codegentest.SampleDataClass.StateName @android.annotation.NonNull java.lang.String mStateName\nprivate @com.android.codegentest.SampleDataClass.RequestFlags int mFlags\nprivate @com.android.codegentest.SampleDataClass.State int mState\npublic @android.annotation.NonNull java.lang.CharSequence charSeq\nprivate final @android.annotation.Nullable android.net.LinkAddress[] mLinkAddresses5\nprivate transient android.net.LinkAddress[] mLinkAddresses6\ntransient int[] mTmpStorage\nprivate @android.annotation.StringRes int mStringRes\nprivate @android.annotation.IntRange(from=0L, to=6L) int mDayOfWeek\nprivate @android.annotation.Size(2L) @android.annotation.NonNull @com.android.internal.util.DataClass.Each @android.annotation.FloatRange(from=0.0) float[] mCoords\nprivate static java.lang.String defaultName4()\nprivate int[] lazyInitTmpStorage()\npublic android.net.LinkAddress[] getLinkAddresses4()\nprivate boolean patternEquals(java.util.regex.Pattern)\nprivate int patternHashCode()\nprivate void onConstructed()\npublic void dump(java.io.PrintWriter)\nclass SampleDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=true, genEqualsHashCode=true, genToString=true, genForEachField=true, genSetters=true)")
@Deprecated
private void __metadata() {}
+
+ //@formatter:on
+ // End of generated code
+
}
diff --git a/tests/Codegen/src/com/android/codegentest/SampleDataClassTest.java b/tests/Codegen/src/com/android/codegentest/SampleDataClassTest.java
index c7a7735..d132577 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleDataClassTest.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleDataClassTest.java
@@ -243,6 +243,26 @@
assertEquals(instance.toString(), unparceledInstance.toString());
}
+ @Test
+ public void testNestedDataClasses_notMangledWhenParceled() {
+ assertEqualsAfterParcelling(
+ new SampleWithNestedDataClasses.NestedDataClass("1"),
+ SampleWithNestedDataClasses.NestedDataClass.CREATOR);
+
+ assertEqualsAfterParcelling(
+ new SampleWithNestedDataClasses.NestedDataClass2("2"),
+ SampleWithNestedDataClasses.NestedDataClass2.CREATOR);
+
+ assertEqualsAfterParcelling(
+ new SampleWithNestedDataClasses.NestedDataClass2.NestedDataClass3(3),
+ SampleWithNestedDataClasses.NestedDataClass2.NestedDataClass3.CREATOR);
+ }
+
+ private static <T extends Parcelable> void assertEqualsAfterParcelling(
+ T p, Parcelable.Creator<T> creator) {
+ assertEquals(p, parcelAndUnparcel(p, creator));
+ }
+
private static <T extends Parcelable> T parcelAndUnparcel(
T original, Parcelable.Creator<T> creator) {
Parcel p = Parcel.obtain();
diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
index 55feae7..cab477d 100644
--- a/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java
@@ -85,7 +85,7 @@
- // Code below generated by codegen v1.0.9.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -224,7 +224,7 @@
}
/** Builds the instance. This builder should not be touched after calling this! */
- public SampleWithCustomBuilder build() {
+ public @NonNull SampleWithCustomBuilder build() {
checkNotUsed();
mBuilderFieldsSet |= 0x8; // Mark builder used
@@ -253,11 +253,15 @@
}
@DataClass.Generated(
- time = 1571258912752L,
- codegenVersion = "1.0.9",
+ time = 1573006403628L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithCustomBuilder.java",
inputSignatures = " long delayAmount\n @android.annotation.NonNull java.util.concurrent.TimeUnit delayUnit\n long creationTimestamp\nprivate static java.util.concurrent.TimeUnit unparcelDelayUnit(android.os.Parcel)\nprivate void parcelDelayUnit(android.os.Parcel,int)\nclass SampleWithCustomBuilder extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genAidl=false, genToString=true)\nabstract com.android.codegentest.SampleWithCustomBuilder.Builder setDelayAmount(long)\npublic abstract com.android.codegentest.SampleWithCustomBuilder.Builder setDelayUnit(java.util.concurrent.TimeUnit)\npublic com.android.codegentest.SampleWithCustomBuilder.Builder setDelay(long,java.util.concurrent.TimeUnit)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}
+
+ //@formatter:on
+ // End of generated code
+
}
diff --git a/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java b/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
new file mode 100644
index 0000000..6190085
--- /dev/null
+++ b/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.codegentest;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * An example of deeply nested data classes
+ */
+public class SampleWithNestedDataClasses {
+
+ int mFoo = 0;
+
+ @DataClass(genEqualsHashCode = true)
+ public static class NestedDataClass implements Parcelable {
+
+ @NonNull String mBar;
+
+
+
+ // Code below generated by codegen v1.0.13.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ public NestedDataClass(
+ @NonNull String bar) {
+ this.mBar = bar;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mBar);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull String getBar() {
+ return mBar;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@android.annotation.Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(NestedDataClass other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ NestedDataClass that = (NestedDataClass) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && java.util.Objects.equals(mBar, that.mBar);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mBar);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeString(mBar);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ protected NestedDataClass(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ String bar = in.readString();
+
+ this.mBar = bar;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mBar);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<NestedDataClass> CREATOR
+ = new Parcelable.Creator<NestedDataClass>() {
+ @Override
+ public NestedDataClass[] newArray(int size) {
+ return new NestedDataClass[size];
+ }
+
+ @Override
+ public NestedDataClass createFromParcel(@NonNull Parcel in) {
+ return new NestedDataClass(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1573006408903L,
+ codegenVersion = "1.0.13",
+ sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java",
+ inputSignatures = " @android.annotation.NonNull java.lang.String mBar\nclass NestedDataClass extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+ }
+
+ @DataClass(genEqualsHashCode = true)
+ public static class NestedDataClass2 implements Parcelable {
+
+ @NonNull String mBaz;
+
+ @DataClass(genEqualsHashCode = true)
+ public static class NestedDataClass3 implements Parcelable {
+
+ @NonNull long mBaz2;
+
+
+
+ // Code below generated by codegen v1.0.13.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ public NestedDataClass3(
+ @NonNull long baz2) {
+ this.mBaz2 = baz2;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mBaz2);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull long getBaz2() {
+ return mBaz2;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@android.annotation.Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(NestedDataClass3 other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ NestedDataClass3 that = (NestedDataClass3) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && mBaz2 == that.mBaz2;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + Long.hashCode(mBaz2);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeLong(mBaz2);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ protected NestedDataClass3(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ long baz2 = in.readLong();
+
+ this.mBaz2 = baz2;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mBaz2);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<NestedDataClass3> CREATOR
+ = new Parcelable.Creator<NestedDataClass3>() {
+ @Override
+ public NestedDataClass3[] newArray(int size) {
+ return new NestedDataClass3[size];
+ }
+
+ @Override
+ public NestedDataClass3 createFromParcel(@NonNull Parcel in) {
+ return new NestedDataClass3(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1573006408912L,
+ codegenVersion = "1.0.13",
+ sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java",
+ inputSignatures = " @android.annotation.NonNull long mBaz2\nclass NestedDataClass3 extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+ }
+
+
+
+ // Code below generated by codegen v1.0.13.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ public NestedDataClass2(
+ @NonNull String baz) {
+ this.mBaz = baz;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mBaz);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public @NonNull String getBaz() {
+ return mBaz;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@android.annotation.Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(NestedDataClass2 other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ NestedDataClass2 that = (NestedDataClass2) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && java.util.Objects.equals(mBaz, that.mBaz);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mBaz);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeString(mBaz);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ protected NestedDataClass2(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ String baz = in.readString();
+
+ this.mBaz = baz;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mBaz);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<NestedDataClass2> CREATOR
+ = new Parcelable.Creator<NestedDataClass2>() {
+ @Override
+ public NestedDataClass2[] newArray(int size) {
+ return new NestedDataClass2[size];
+ }
+
+ @Override
+ public NestedDataClass2 createFromParcel(@NonNull Parcel in) {
+ return new NestedDataClass2(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1573006408917L,
+ codegenVersion = "1.0.13",
+ sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/SampleWithNestedDataClasses.java",
+ inputSignatures = " @android.annotation.NonNull java.lang.String mBaz\nclass NestedDataClass2 extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+ }
+
+ void someCode() {}
+}
diff --git a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
index b967f19..5a960d7 100644
--- a/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
+++ b/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java
@@ -51,7 +51,7 @@
- // Code below generated by codegen v1.0.9.
+ // Code below generated by codegen v1.0.13.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -65,11 +65,15 @@
@DataClass.Generated(
- time = 1571258916868L,
- codegenVersion = "1.0.9",
+ time = 1573006407900L,
+ codegenVersion = "1.0.13",
sourceFile = "frameworks/base/tests/Codegen/src/com/android/codegentest/StaleDataclassDetectorFalsePositivesTest.java",
inputSignatures = "public @android.annotation.NonNull java.lang.String someMethod(int)\nclass StaleDataclassDetectorFalsePositivesTest extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=false)")
@Deprecated
private void __metadata() {}
+
+ //@formatter:on
+ // End of generated code
+
}
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index bfb4968..06be5e2 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -21,8 +21,6 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.fail;
-
import android.Manifest;
import android.annotation.Nullable;
import android.content.ComponentName;
@@ -30,13 +28,14 @@
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
+import android.content.pm.PackageManager;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
import android.os.ParcelFileDescriptor;
import android.provider.DeviceConfig;
import android.text.TextUtils;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.cts.install.lib.Install;
import com.android.cts.install.lib.InstallUtils;
@@ -55,6 +54,7 @@
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.io.File;
import java.util.concurrent.TimeUnit;
/**
@@ -72,8 +72,13 @@
"android.net.INetworkStackConnector";
private static final String PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT =
"watchdog_trigger_failure_count";
+ private static final String PROPERTY_WATCHDOG_REQUEST_TIMEOUT_MILLIS =
+ "watchdog_request_timeout_millis";
private static final String MODULE_META_DATA_PACKAGE = getModuleMetadataPackageName();
+ private static final TestApp NETWORK_STACK = new TestApp("NetworkStack",
+ getNetworkStackPackageName(), -1, false,
+ new File("/system/priv-app/NetworkStack/NetworkStack.apk"));
/**
* Adopts common shell permissions needed for rollback tests.
@@ -148,10 +153,9 @@
RollbackUtils.sendCrashBroadcast(TestApp.A, 1);
// We expect the device to be rebooted automatically. Wait for that to happen.
- Thread.sleep(30 * 1000);
-
- // Raise an error anyway if reboot didn't happen.
- fail("watchdog did not trigger reboot");
+ // This device method will fail and the host will catch the assertion.
+ // If reboot doesn't happen, the host will fail the assertion.
+ Thread.sleep(TimeUnit.SECONDS.toMillis(120));
}
/**
@@ -180,7 +184,7 @@
@Test
public void testNativeWatchdogTriggersRollback_Phase1() throws Exception {
resetModuleMetadataPackage();
- Context context = InstrumentationRegistry.getContext();
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
PackageInfo metadataPackageInfo = context.getPackageManager().getPackageInfo(
MODULE_META_DATA_PACKAGE, 0);
String metadataApkPath = metadataPackageInfo.applicationInfo.sourceDir;
@@ -214,6 +218,7 @@
@Test
public void testNetworkFailedRollback_Phase1() throws Exception {
+ // Remove available rollbacks and uninstall NetworkStack on /data/
RollbackManager rm = RollbackUtils.getRollbackManager();
String networkStack = getNetworkStackPackageName();
@@ -222,6 +227,13 @@
assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
networkStack)).isNull();
+
+ // Reduce health check deadline
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
+ PROPERTY_WATCHDOG_REQUEST_TIMEOUT_MILLIS,
+ Integer.toString(120000), false);
+ // Simulate re-installation of new NetworkStack with rollbacks enabled
+ installNetworkStackPackage();
}
@Test
@@ -239,11 +251,11 @@
@Test
public void testNetworkFailedRollback_Phase3() throws Exception {
- // Sleep for > health check deadline
+ // Sleep for > health check deadline (120s to trigger rollback + 120s to reboot)
// The device is expected to reboot during sleeping. This device method will fail and
// the host will catch the assertion. If reboot doesn't happen, the host will fail the
// assertion.
- Thread.sleep(TimeUnit.SECONDS.toMillis(120));
+ Thread.sleep(TimeUnit.SECONDS.toMillis(240));
}
@Test
@@ -253,16 +265,20 @@
getNetworkStackPackageName())).isNotNull();
}
- private String getNetworkStackPackageName() {
+ private static String getNetworkStackPackageName() {
Intent intent = new Intent(NETWORK_STACK_CONNECTOR_CLASS);
ComponentName comp = intent.resolveSystemService(
- InstrumentationRegistry.getContext().getPackageManager(), 0);
+ InstrumentationRegistry.getInstrumentation().getContext().getPackageManager(), 0);
return comp.getPackageName();
}
- private void uninstallNetworkStackPackage() {
- // Since the host side use shell command to install the network stack package, uninstall
- // must be done by shell command as well. Otherwise uninstall by a different user will fail.
+ private static void installNetworkStackPackage() throws Exception {
+ Install.single(NETWORK_STACK).setStaged().setEnableRollback()
+ .addInstallFlags(PackageManager.INSTALL_REPLACE_EXISTING).commit();
+ }
+
+ private static void uninstallNetworkStackPackage() {
+ // Uninstall the package as a privileged user so we won't fail due to permission.
runShellCommand("pm uninstall " + getNetworkStackPackageName());
}
@@ -273,8 +289,8 @@
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
int sessionId = Install.single(TestApp.A2).setStaged().setEnableRollback().commit();
- PackageInstaller pi = InstrumentationRegistry.getContext().getPackageManager()
- .getPackageInstaller();
+ PackageInstaller pi = InstrumentationRegistry.getInstrumentation().getContext()
+ .getPackageManager().getPackageInstaller();
pi.abandonSession(sessionId);
// Remove the first intent sender result, so that the next staged install session does not
@@ -330,8 +346,8 @@
@Nullable
private static String getModuleMetadataPackageName() {
- String packageName = InstrumentationRegistry.getContext().getResources().getString(
- R.string.config_defaultModuleMetadataProvider);
+ String packageName = InstrumentationRegistry.getInstrumentation().getContext()
+ .getResources().getString(R.string.config_defaultModuleMetadataProvider);
if (TextUtils.isEmpty(packageName)) {
return null;
}
@@ -348,7 +364,7 @@
MODULE_META_DATA_PACKAGE)).isNull();
}
- private void runShellCommand(String cmd) {
+ private static void runShellCommand(String cmd) {
ParcelFileDescriptor pfd = InstrumentationRegistry.getInstrumentation().getUiAutomation()
.executeShellCommand(cmd);
IoUtils.closeQuietly(pfd);
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index c10169b..557d498 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -19,13 +19,11 @@
import static org.junit.Assert.assertTrue;
import static org.testng.Assert.assertThrows;
-import com.android.ddmlib.Log.LogLevel;
-import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -52,16 +50,7 @@
@Before
public void setUp() throws Exception {
- // Disconnect internet so we can test network health triggered rollbacks
- getDevice().executeShellCommand("svc wifi disable");
- getDevice().executeShellCommand("svc data disable");
- }
-
- @After
- public void tearDown() throws Exception {
- // Reconnect internet after testing network health triggered rollbacks
- getDevice().executeShellCommand("svc wifi enable");
- getDevice().executeShellCommand("svc data enable");
+ getDevice().reboot();
}
/**
@@ -72,17 +61,8 @@
runPhase("testBadApkOnly_Phase1");
getDevice().reboot();
runPhase("testBadApkOnly_Phase2");
- try {
- // This is expected to fail due to the device being rebooted out
- // from underneath the test. If this fails for reasons other than
- // the device reboot, those failures should result in failure of
- // the testApkOnlyConfirmRollback phase.
- CLog.logAndDisplay(LogLevel.INFO, "testBadApkOnlyTriggerRollback is expected to fail");
- runPhase("testBadApkOnly_Phase3");
- } catch (AssertionError e) {
- // AssertionError is expected.
- }
+ assertThrows(AssertionError.class, () -> runPhase("testBadApkOnly_Phase3"));
getDevice().waitForDeviceAvailable();
runPhase("testBadApkOnly_Phase4");
@@ -121,33 +101,34 @@
*/
@Test
public void testNetworkFailedRollback() throws Exception {
- // Remove available rollbacks and uninstall NetworkStack on /data/
- runPhase("testNetworkFailedRollback_Phase1");
- // Reduce health check deadline
- getDevice().executeShellCommand("device_config put rollback "
- + "watchdog_request_timeout_millis 120000");
- // Simulate re-installation of new NetworkStack with rollbacks enabled
- getDevice().executeShellCommand("pm install -r --staged --enable-rollback "
- + "/system/priv-app/NetworkStack/NetworkStack.apk");
+ try {
+ // Disconnect internet so we can test network health triggered rollbacks
+ getDevice().executeShellCommand("svc wifi disable");
+ getDevice().executeShellCommand("svc data disable");
- // Sleep to allow writes to disk before reboot
- Thread.sleep(5000);
- // Reboot device to activate staged package
- getDevice().reboot();
+ runPhase("testNetworkFailedRollback_Phase1");
+ // Reboot device to activate staged package
+ getDevice().reboot();
- // Verify rollback was enabled
- runPhase("testNetworkFailedRollback_Phase2");
- assertThrows(AssertionError.class, () -> runPhase("testNetworkFailedRollback_Phase3"));
+ // Verify rollback was enabled
+ runPhase("testNetworkFailedRollback_Phase2");
+ assertThrows(AssertionError.class, () -> runPhase("testNetworkFailedRollback_Phase3"));
- getDevice().waitForDeviceAvailable();
- // Verify rollback was executed after health check deadline
- runPhase("testNetworkFailedRollback_Phase4");
+ getDevice().waitForDeviceAvailable();
+ // Verify rollback was executed after health check deadline
+ runPhase("testNetworkFailedRollback_Phase4");
+ } finally {
+ // Reconnect internet again so we won't break tests which assume internet available
+ getDevice().executeShellCommand("svc wifi enable");
+ getDevice().executeShellCommand("svc data enable");
+ }
}
/**
* Tests passed network health check does not trigger watchdog staged rollbacks.
*/
@Test
+ @Ignore("b/143514090")
public void testNetworkPassedDoesNotRollback() throws Exception {
// Remove available rollbacks and uninstall NetworkStack on /data/
runPhase("testNetworkPassedDoesNotRollback_Phase1");
diff --git a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
index ba77a74..1664746 100644
--- a/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
+++ b/tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
@@ -73,6 +73,10 @@
mFps = 0;
mLastFpsUpdate = 0;
mFrameCount = 0;
+
+ mDf = new DecimalFormat("fps: #.##");
+ mDf.setRoundingMode(RoundingMode.HALF_UP);
+
Trace.endSection();
}
@@ -181,9 +185,7 @@
// Draw the ball
canvas.drawColor(BACKGROUND_COLOR);
canvas.drawOval(left, top, right, bottom, getBallColor());
- DecimalFormat df = new DecimalFormat("fps: #.##");
- df.setRoundingMode(RoundingMode.HALF_UP);
- canvas.drawText(df.format(mFps), width, 100, mTextPaint);
+ canvas.drawText(mDf.format(mFps), width, 100, mTextPaint);
invalidate();
Trace.endSection();
@@ -220,6 +222,7 @@
private long mLastDrawNano, mLastFpsUpdate, mFrameCount;
private float mFps;
+ private DecimalFormat mDf;
}
public class TouchLatencyActivity extends Activity {
diff --git a/tools/apilint/apilint b/tools/apilint/apilint
deleted file mode 100755
index e42857f..0000000
--- a/tools/apilint/apilint
+++ /dev/null
@@ -1,147 +0,0 @@
-#!/bin/bash
-
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the 'License');
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an 'AS IS' BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if [ "$1" == "--help" -o "$1" == "-h" ]; then
-echo "Usage: apilint [FILTERS...]"
-echo " Shows lint from currently open files (as diffed from HEAD), i.e. errors"
-echo " you will receive if you upload this CL."
-echo
-echo "Usage: apilint --all [FILTERS...]"
-echo " Shows all lint errors present in the current working directory, regardless"
-echo " of when they were added."
-echo
-echo "Usage: apilint --level API_LEVEL [FILTERS...]"
-echo " Shows lint as it stands in API_LEVEL"
-echo
-echo "Usage: apilint --shal SHA [FILTERS...]"
-echo " Shows lint from locally commited git change SHA."
-echo
-echo "Usage: apilint --unreleased [FILTERS...]"
-echo " Shows all lint errors in the current working directory directory added since"
-echo " the last released SDK version."
-echo
-echo "FILTERS"
-echo " List of class or package names by which to filter the results."
-echo
-exit
-fi
-
-if [ \( -z "$ANDROID_BUILD_TOP" \) \
- -a \( ! -f frameworks/base/api/current.txt \) \
- -a \( ! -f frameworks/base/api/system-current.txt \) \
- ]; then
- echo "apilint must be run either with ANDROID_BUILD_TOP set or from the" 1>&2
- echo "root of the android source tree" 1>&2
- exit 1
-fi
-
-if [ ${ANDROID_BUILD_TOP:0:1} != "/" ]; then
- echo "ANDROID_BUILD_TOP must be an absolute path, not: $ANDROID_BUILD_TOP" 1>&2
- exit 1
-fi
-
-if [ -z "$ANDROID_BUILD_TOP" ]; then
- ANDROID_BUILD_TOP=$(pwd)
-fi
-
-FW_BASE=$ANDROID_BUILD_TOP/frameworks/base
-
-MODE=open
-
-OPTIONS=$(getopt -n apilint -o "" -l "all,sha:,unreleased" -- "$@")
-
-[ $? -eq 0 ] || {
- exit 1
-}
-
-eval set -- "$OPTIONS"
-while true; do
- case "$1" in
- --all)
- MODE=all
- ;;
- --sha)
- shift; # The arg is next in position args
- MODE=sha
- SHA=$1
- ;;
- --unreleased)
- MODE=unreleased
- ;;
- --)
- shift
- break
- ;;
- esac
- shift
-done
-FILTERS=
-for var in "$@"
-do
- FILTERS="$FILTERS --filter $var"
-done
-
-if [ $MODE = "all" ]; then
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SDK" \
- $FILTERS \
- $ANDROID_BUILD_TOP/frameworks/base/api/current.txt
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SystemApi" \
- $FILTERS \
- --base-current $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \
- $ANDROID_BUILD_TOP/frameworks/base/api/system-current.txt
-elif [ $MODE = "open" ]; then
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SDK" \
- $FILTERS \
- $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \
- <(cd $FW_BASE ; git show HEAD:api/current.txt)
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SystemApi" \
- $FILTERS \
- --base-current $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \
- --base-previous <(cd $FW_BASE ; git show HEAD:api/current.txt) \
- $ANDROID_BUILD_TOP/frameworks/base/api/system-current.txt \
- <(cd $FW_BASE ; git show HEAD:api/system-current.txt)
-elif [ $MODE = "sha" ]; then
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SDK" \
- $FILTERS \
- <(cd $FW_BASE ; git show $SHA:api/current.txt) \
- <(cd $FW_BASE ; git show $SHA^:api/current.txt)
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SystemApi" \
- $FILTERS \
- --base-current <(cd $FW_BASE ; git show $SHA:api/current.txt) \
- --base-previous <(cd $FW_BASE ; git show $SHA^:api/current.txt) \
- <(cd $FW_BASE ; git show $SHA:api/system-current.txt) \
- <(cd $FW_BASE ; git show $SHA^:api/system-current.txt)
-elif [ $MODE = "unreleased" ]; then
- LAST_SDK=$(ls $ANDROID_BUILD_TOP/prebuilts/sdk | grep "^[0-9][0-9]*$" | sort -n | tail -n 1)
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SDK" \
- $FILTERS \
- $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \
- $ANDROID_BUILD_TOP/prebuilts/sdk/$LAST_SDK/public/api/android.txt
- python2.7 -B $ANDROID_BUILD_TOP/frameworks/base/tools/apilint/apilint.py \
- --title "SystemApi" \
- $FILTERS \
- --base-current $ANDROID_BUILD_TOP/frameworks/base/api/current.txt \
- --base-previous $ANDROID_BUILD_TOP/prebuilts/sdk/$LAST_SDK/public/api/android.txt \
- $ANDROID_BUILD_TOP/frameworks/base/api/system-current.txt \
- $ANDROID_BUILD_TOP/prebuilts/sdk/$LAST_SDK/system/api/android.txt
-fi
diff --git a/tools/apilint/apilint.py b/tools/apilint/apilint.py
deleted file mode 100644
index 912c1ad..0000000
--- a/tools/apilint/apilint.py
+++ /dev/null
@@ -1,2353 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (C) 2014 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the 'License');
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an 'AS IS' BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""
-Enforces common Android public API design patterns. It ignores lint messages from
-a previous API level, if provided.
-
-Usage: apilint.py current.txt
-Usage: apilint.py current.txt previous.txt
-
-You can also splice in blame details like this:
-$ git blame api/current.txt -t -e > /tmp/currentblame.txt
-$ apilint.py /tmp/currentblame.txt previous.txt --no-color
-"""
-
-import re, sys, collections, traceback, argparse, itertools
-
-
-BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
-
-ALLOW_GOOGLE = False
-USE_COLOR = True
-
-def format(fg=None, bg=None, bright=False, bold=False, dim=False, reset=False):
- # manually derived from http://en.wikipedia.org/wiki/ANSI_escape_code#Codes
- if not USE_COLOR: return ""
- codes = []
- if reset: codes.append("0")
- else:
- if not fg is None: codes.append("3%d" % (fg))
- if not bg is None:
- if not bright: codes.append("4%d" % (bg))
- else: codes.append("10%d" % (bg))
- if bold: codes.append("1")
- elif dim: codes.append("2")
- else: codes.append("22")
- return "\033[%sm" % (";".join(codes))
-
-
-class Field():
- def __init__(self, clazz, line, raw, blame, sig_format = 1):
- self.clazz = clazz
- self.line = line
- self.raw = raw.strip(" {;")
- self.blame = blame
-
- if sig_format == 2:
- V2LineParser(raw).parse_into_field(self)
- elif sig_format == 1:
- # drop generics for now; may need multiple passes
- raw = re.sub("<[^<]+?>", "", raw)
- raw = re.sub("<[^<]+?>", "", raw)
-
- raw = raw.split()
- self.split = list(raw)
-
- for r in ["field", "volatile", "transient", "public", "protected", "static", "final", "deprecated"]:
- while r in raw: raw.remove(r)
-
- # ignore annotations for now
- raw = [ r for r in raw if not r.startswith("@") ]
-
- self.typ = raw[0]
- self.name = raw[1].strip(";")
- if len(raw) >= 4 and raw[2] == "=":
- self.value = raw[3].strip(';"')
- else:
- self.value = None
- self.annotations = []
-
- self.ident = "-".join((self.typ, self.name, self.value or ""))
-
- def __hash__(self):
- return hash(self.raw)
-
- def __repr__(self):
- return self.raw
-
-
-class Argument(object):
-
- __slots__ = ["type", "annotations", "name", "default"]
-
- def __init__(self, type):
- self.type = type
- self.annotations = []
- self.name = None
- self.default = None
-
-
-class Method():
- def __init__(self, clazz, line, raw, blame, sig_format = 1):
- self.clazz = clazz
- self.line = line
- self.raw = raw.strip(" {;")
- self.blame = blame
-
- if sig_format == 2:
- V2LineParser(raw).parse_into_method(self)
- elif sig_format == 1:
- # drop generics for now; may need multiple passes
- raw = re.sub("<[^<]+?>", "", raw)
- raw = re.sub("<[^<]+?>", "", raw)
-
- # handle each clause differently
- raw_prefix, raw_args, _, raw_throws = re.match(r"(.*?)\((.*?)\)( throws )?(.*?);$", raw).groups()
-
- # parse prefixes
- raw = re.split("[\s]+", raw_prefix)
- for r in ["", ";"]:
- while r in raw: raw.remove(r)
- self.split = list(raw)
-
- for r in ["method", "public", "protected", "static", "final", "deprecated", "abstract", "default", "operator", "synchronized"]:
- while r in raw: raw.remove(r)
-
- self.typ = raw[0]
- self.name = raw[1]
-
- # parse args
- self.detailed_args = []
- for arg in re.split(",\s*", raw_args):
- arg = re.split("\s", arg)
- # ignore annotations for now
- arg = [ a for a in arg if not a.startswith("@") ]
- if len(arg[0]) > 0:
- self.detailed_args.append(Argument(arg[0]))
-
- # parse throws
- self.throws = []
- for throw in re.split(",\s*", raw_throws):
- self.throws.append(throw)
-
- self.annotations = []
- else:
- raise ValueError("Unknown signature format: " + sig_format)
-
- self.args = map(lambda a: a.type, self.detailed_args)
- self.ident = "-".join((self.typ, self.name, "-".join(self.args)))
-
- def sig_matches(self, typ, name, args):
- return typ == self.typ and name == self.name and args == self.args
-
- def __hash__(self):
- return hash(self.raw)
-
- def __repr__(self):
- return self.raw
-
-
-class Class():
- def __init__(self, pkg, line, raw, blame, sig_format = 1):
- self.pkg = pkg
- self.line = line
- self.raw = raw.strip(" {;")
- self.blame = blame
- self.ctors = []
- self.fields = []
- self.methods = []
- self.annotations = []
-
- if sig_format == 2:
- V2LineParser(raw).parse_into_class(self)
- elif sig_format == 1:
- # drop generics for now; may need multiple passes
- raw = re.sub("<[^<]+?>", "", raw)
- raw = re.sub("<[^<]+?>", "", raw)
-
- raw = raw.split()
- self.split = list(raw)
- if "class" in raw:
- self.fullname = raw[raw.index("class")+1]
- elif "interface" in raw:
- self.fullname = raw[raw.index("interface")+1]
- elif "@interface" in raw:
- self.fullname = raw[raw.index("@interface")+1]
- else:
- raise ValueError("Funky class type %s" % (self.raw))
-
- if "extends" in raw:
- self.extends = raw[raw.index("extends")+1]
- else:
- self.extends = None
-
- if "implements" in raw:
- self.implements = raw[raw.index("implements")+1]
- self.implements_all = [self.implements]
- else:
- self.implements = None
- self.implements_all = []
- else:
- raise ValueError("Unknown signature format: " + sig_format)
-
- self.fullname = self.pkg.name + "." + self.fullname
- self.fullname_path = self.fullname.split(".")
-
- if self.extends is not None:
- self.extends_path = self.extends.split(".")
- else:
- self.extends_path = []
-
- self.name = self.fullname[self.fullname.rindex(".")+1:]
-
- def merge_from(self, other):
- self.ctors.extend(other.ctors)
- self.fields.extend(other.fields)
- self.methods.extend(other.methods)
-
- def __hash__(self):
- return hash((self.raw, tuple(self.ctors), tuple(self.fields), tuple(self.methods)))
-
- def __repr__(self):
- return self.raw
-
-
-class Package():
- NAME = re.compile("package(?: .*)? ([A-Za-z0-9.]+)")
-
- def __init__(self, line, raw, blame):
- self.line = line
- self.raw = raw.strip(" {;")
- self.blame = blame
-
- self.name = Package.NAME.match(raw).group(1)
- self.name_path = self.name.split(".")
-
- def __repr__(self):
- return self.raw
-
-class V2Tokenizer(object):
- __slots__ = ["raw"]
-
- SIGNATURE_PREFIX = "// Signature format: "
- DELIMITER = re.compile(r'\s+|[()@<>;,={}/"!?]|\[\]|\.\.\.')
- STRING_SPECIAL = re.compile(r'["\\]')
-
- def __init__(self, raw):
- self.raw = raw
-
- def tokenize(self):
- tokens = []
- current = 0
- raw = self.raw
- length = len(raw)
-
- while current < length:
- while current < length:
- start = current
- match = V2Tokenizer.DELIMITER.search(raw, start)
- if match is not None:
- match_start = match.start()
- if match_start == current:
- end = match.end()
- else:
- end = match_start
- else:
- end = length
-
- token = raw[start:end]
- current = end
-
- if token == "" or token[0] == " ":
- continue
- else:
- break
-
- if token == "@":
- if raw[start:start+11] == "@interface ":
- current = start + 11
- tokens.append("@interface")
- continue
- elif token == '/':
- if raw[start:start+2] == "//":
- current = length
- continue
- elif token == '"':
- current, string_token = self.tokenize_string(raw, length, current)
- tokens.append(token + string_token)
- continue
-
- tokens.append(token)
-
- return tokens
-
- def tokenize_string(self, raw, length, current):
- start = current
- end = length
- while start < end:
- match = V2Tokenizer.STRING_SPECIAL.search(raw, start)
- if match:
- if match.group() == '"':
- end = match.end()
- break
- elif match.group() == '\\':
- # ignore whatever is after the slash
- start += 2
- else:
- raise ValueError("Unexpected match: `%s`" % (match.group()))
- else:
- raise ValueError("Unexpected EOF tokenizing string: `%s`" % (raw[current - 1:],))
-
- token = raw[current:end]
- return end, token
-
-class V2LineParser(object):
- __slots__ = ["tokenized", "current", "len"]
-
- FIELD_KINDS = ("field", "property", "enum_constant")
- MODIFIERS = set("public protected internal private abstract default static final transient volatile synchronized native operator sealed strictfp infix inline suspend vararg".split())
- JAVA_LANG_TYPES = set("AbstractMethodError AbstractStringBuilder Appendable ArithmeticException ArrayIndexOutOfBoundsException ArrayStoreException AssertionError AutoCloseable Boolean BootstrapMethodError Byte Character CharSequence Class ClassCastException ClassCircularityError ClassFormatError ClassLoader ClassNotFoundException Cloneable CloneNotSupportedException Comparable Compiler Deprecated Double Enum EnumConstantNotPresentException Error Exception ExceptionInInitializerError Float FunctionalInterface IllegalAccessError IllegalAccessException IllegalArgumentException IllegalMonitorStateException IllegalStateException IllegalThreadStateException IncompatibleClassChangeError IndexOutOfBoundsException InheritableThreadLocal InstantiationError InstantiationException Integer InternalError InterruptedException Iterable LinkageError Long Math NegativeArraySizeException NoClassDefFoundError NoSuchFieldError NoSuchFieldException NoSuchMethodError NoSuchMethodException NullPointerException Number NumberFormatException Object OutOfMemoryError Override Package package-info.java Process ProcessBuilder ProcessEnvironment ProcessImpl Readable ReflectiveOperationException Runnable Runtime RuntimeException RuntimePermission SafeVarargs SecurityException SecurityManager Short StackOverflowError StackTraceElement StrictMath String StringBuffer StringBuilder StringIndexOutOfBoundsException SuppressWarnings System Thread ThreadDeath ThreadGroup ThreadLocal Throwable TypeNotPresentException UNIXProcess UnknownError UnsatisfiedLinkError UnsupportedClassVersionError UnsupportedOperationException VerifyError VirtualMachineError Void".split())
-
- def __init__(self, raw):
- self.tokenized = V2Tokenizer(raw).tokenize()
- self.current = 0
- self.len = len(self.tokenized)
-
- def parse_into_method(self, method):
- method.split = []
- kind = self.parse_one_of("ctor", "method")
- method.split.append(kind)
- method.annotations = self.parse_annotations()
- method.split.extend(self.parse_modifiers())
- self.parse_matching_paren("<", ">")
- if "@Deprecated" in method.annotations:
- method.split.append("deprecated")
- if kind == "ctor":
- method.typ = "ctor"
- else:
- method.typ = self.parse_type()
- method.split.append(method.typ)
- method.name = self.parse_name()
- method.split.append(method.name)
- self.parse_token("(")
- method.detailed_args = self.parse_args()
- self.parse_token(")")
- method.throws = self.parse_throws()
- if "@interface" in method.clazz.split:
- self.parse_annotation_default()
- self.parse_token(";")
- self.parse_eof()
-
- def parse_into_class(self, clazz):
- clazz.split = []
- clazz.annotations = self.parse_annotations()
- if "@Deprecated" in clazz.annotations:
- clazz.split.append("deprecated")
- clazz.split.extend(self.parse_modifiers())
- kind = self.parse_one_of("class", "interface", "@interface", "enum")
- if kind == "enum":
- # enums are implicitly final
- clazz.split.append("final")
- clazz.split.append(kind)
- clazz.fullname = self.parse_name()
- self.parse_matching_paren("<", ">")
- extends = self.parse_extends()
- clazz.extends = extends[0] if extends else None
- clazz.implements_all = self.parse_implements()
- # The checks assume that interfaces are always found in implements, which isn't true for
- # subinterfaces.
- if not clazz.implements_all and "interface" in clazz.split:
- clazz.implements_all = [clazz.extends]
- clazz.implements = clazz.implements_all[0] if clazz.implements_all else None
- self.parse_token("{")
- self.parse_eof()
-
- def parse_into_field(self, field):
- kind = self.parse_one_of(*V2LineParser.FIELD_KINDS)
- field.split = [kind]
- field.annotations = self.parse_annotations()
- if "@Deprecated" in field.annotations:
- field.split.append("deprecated")
- field.split.extend(self.parse_modifiers())
- field.typ = self.parse_type()
- field.split.append(field.typ)
- field.name = self.parse_name()
- field.split.append(field.name)
- if self.parse_if("="):
- field.value = self.parse_value_stripped()
- else:
- field.value = None
-
- self.parse_token(";")
- self.parse_eof()
-
- def lookahead(self):
- return self.tokenized[self.current]
-
- def parse_one_of(self, *options):
- found = self.lookahead()
- if found not in options:
- raise ValueError("Parsing failed, expected one of `%s` but found `%s` in %s" % (options, found, repr(self.tokenized)))
- return self.parse_token()
-
- def parse_token(self, tok = None):
- found = self.lookahead()
- if tok is not None and found != tok:
- raise ValueError("Parsing failed, expected `%s` but found `%s` in %s" % (tok, found, repr(self.tokenized)))
- self.current += 1
- return found
-
- def eof(self):
- return self.current == self.len
-
- def parse_eof(self):
- if not self.eof():
- raise ValueError("Parsing failed, expected EOF, but %s has not been parsed in %s" % (self.tokenized[self.current:], self.tokenized))
-
- def parse_if(self, tok):
- if not self.eof() and self.lookahead() == tok:
- self.parse_token()
- return True
- return False
-
- def parse_annotations(self):
- ret = []
- while self.lookahead() == "@":
- ret.append(self.parse_annotation())
- return ret
-
- def parse_annotation(self):
- ret = self.parse_token("@") + self.parse_token()
- self.parse_matching_paren("(", ")")
- return ret
-
- def parse_matching_paren(self, open, close):
- start = self.current
- if not self.parse_if(open):
- return
- length = len(self.tokenized)
- count = 1
- while count > 0:
- if self.current == length:
- raise ValueError("Unexpected EOF looking for closing paren: `%s`" % (self.tokenized[start:],))
- t = self.parse_token()
- if t == open:
- count += 1
- elif t == close:
- count -= 1
- return self.tokenized[start:self.current]
-
- def parse_modifiers(self):
- ret = []
- while self.lookahead() in V2LineParser.MODIFIERS:
- ret.append(self.parse_token())
- return ret
-
- def parse_kotlin_nullability(self):
- t = self.lookahead()
- if t == "?" or t == "!":
- return self.parse_token()
- return None
-
- def parse_type(self):
- self.parse_annotations()
- type = self.parse_token()
- if type[-1] == '.':
- self.parse_annotations()
- type += self.parse_token()
- if type in V2LineParser.JAVA_LANG_TYPES:
- type = "java.lang." + type
- self.parse_matching_paren("<", ">")
- while True:
- t = self.lookahead()
- if t == "@":
- self.parse_annotation()
- elif t == "[]":
- type += self.parse_token()
- elif self.parse_kotlin_nullability() is not None:
- pass # discard nullability for now
- else:
- break
- return type
-
- def parse_arg_type(self):
- type = self.parse_type()
- if self.parse_if("..."):
- type += "..."
- self.parse_kotlin_nullability() # discard nullability for now
- return type
-
- def parse_name(self):
- return self.parse_token()
-
- def parse_args(self):
- args = []
- if self.lookahead() == ")":
- return args
-
- while True:
- args.append(self.parse_arg())
- if self.lookahead() == ")":
- return args
- self.parse_token(",")
-
- def parse_arg(self):
- self.parse_if("vararg") # kotlin vararg
- annotations = self.parse_annotations()
- arg = Argument(self.parse_arg_type())
- arg.annotations = annotations
- l = self.lookahead()
- if l != "," and l != ")":
- if self.lookahead() != '=':
- arg.name = self.parse_token() # kotlin argument name
- if self.parse_if('='): # kotlin default value
- arg.default = self.parse_expression()
- return arg
-
- def parse_expression(self):
- while not self.lookahead() in [')', ',', ';']:
- (self.parse_matching_paren('(', ')') or
- self.parse_matching_paren('{', '}') or
- self.parse_token())
-
- def parse_throws(self):
- ret = []
- if self.parse_if("throws"):
- ret.append(self.parse_type())
- while self.parse_if(","):
- ret.append(self.parse_type())
- return ret
-
- def parse_extends(self):
- if self.parse_if("extends"):
- return self.parse_space_delimited_type_list()
- return []
-
- def parse_implements(self):
- if self.parse_if("implements"):
- return self.parse_space_delimited_type_list()
- return []
-
- def parse_space_delimited_type_list(self, terminals = ["implements", "{"]):
- types = []
- while True:
- types.append(self.parse_type())
- if self.lookahead() in terminals:
- return types
-
- def parse_annotation_default(self):
- if self.parse_if("default"):
- self.parse_expression()
-
- def parse_value(self):
- if self.lookahead() == "{":
- return " ".join(self.parse_matching_paren("{", "}"))
- elif self.lookahead() == "(":
- return " ".join(self.parse_matching_paren("(", ")"))
- else:
- return self.parse_token()
-
- def parse_value_stripped(self):
- value = self.parse_value()
- if value[0] == '"':
- return value[1:-1]
- return value
-
-
-def _parse_stream(f, clazz_cb=None, base_f=None, out_classes_with_base=None,
- in_classes_with_base=[]):
- api = {}
- in_classes_with_base = _retry_iterator(in_classes_with_base)
-
- if base_f:
- base_classes = _retry_iterator(_parse_stream_to_generator(base_f))
- else:
- base_classes = []
-
- def handle_class(clazz):
- if clazz_cb:
- clazz_cb(clazz)
- else: # In callback mode, don't keep track of the full API
- api[clazz.fullname] = clazz
-
- def handle_missed_classes_with_base(clazz):
- for c in _yield_until_matching_class(in_classes_with_base, clazz):
- base_class = _skip_to_matching_class(base_classes, c)
- if base_class:
- handle_class(base_class)
-
- for clazz in _parse_stream_to_generator(f):
- # Before looking at clazz, let's see if there's some classes that were not present, but
- # may have an entry in the base stream.
- handle_missed_classes_with_base(clazz)
-
- base_class = _skip_to_matching_class(base_classes, clazz)
- if base_class:
- clazz.merge_from(base_class)
- if out_classes_with_base is not None:
- out_classes_with_base.append(clazz)
- handle_class(clazz)
-
- handle_missed_classes_with_base(None)
-
- return api
-
-def _parse_stream_to_generator(f):
- line = 0
- pkg = None
- clazz = None
- blame = None
- sig_format = 1
-
- re_blame = re.compile(r"^(\^?[a-z0-9]{7,}) \(<([^>]+)>.+?\) (.+?)$")
-
- field_prefixes = map(lambda kind: " %s" % (kind,), V2LineParser.FIELD_KINDS)
- def startsWithFieldPrefix(raw):
- for prefix in field_prefixes:
- if raw.startswith(prefix):
- return True
- return False
-
- for raw in f:
- line += 1
- raw = raw.rstrip()
- match = re_blame.match(raw)
- if match is not None:
- blame = match.groups()[0:2]
- if blame[0].startswith("^"): # Outside of blame range
- blame = None
- raw = match.groups()[2]
- else:
- blame = None
-
- if line == 1 and V2Tokenizer.SIGNATURE_PREFIX in raw:
- sig_format_string = raw[len(V2Tokenizer.SIGNATURE_PREFIX):]
- if sig_format_string in ["2.0", "3.0"]:
- sig_format = 2
- else:
- raise ValueError("Unknown format: %s" % (sig_format_string,))
- elif raw.startswith("package"):
- pkg = Package(line, raw, blame)
- elif raw.startswith(" ") and raw.endswith("{"):
- clazz = Class(pkg, line, raw, blame, sig_format=sig_format)
- elif raw.startswith(" ctor"):
- clazz.ctors.append(Method(clazz, line, raw, blame, sig_format=sig_format))
- elif raw.startswith(" method"):
- clazz.methods.append(Method(clazz, line, raw, blame, sig_format=sig_format))
- elif startsWithFieldPrefix(raw):
- clazz.fields.append(Field(clazz, line, raw, blame, sig_format=sig_format))
- elif raw.startswith(" }") and clazz:
- yield clazz
-
-def _retry_iterator(it):
- """Wraps an iterator, such that calling send(True) on it will redeliver the same element"""
- for e in it:
- while True:
- retry = yield e
- if not retry:
- break
- # send() was called, asking us to redeliver clazz on next(). Still need to yield
- # a dummy value to the send() first though.
- if (yield "Returning clazz on next()"):
- raise TypeError("send() must be followed by next(), not send()")
-
-def _skip_to_matching_class(classes, needle):
- """Takes a classes iterator and consumes entries until it returns the class we're looking for
-
- This relies on classes being sorted by package and class name."""
-
- for clazz in classes:
- if clazz.pkg.name < needle.pkg.name:
- # We haven't reached the right package yet
- continue
- if clazz.pkg.name == needle.pkg.name and clazz.fullname < needle.fullname:
- # We're in the right package, but not the right class yet
- continue
- if clazz.fullname == needle.fullname:
- return clazz
- # We ran past the right class. Send it back into the generator, then report failure.
- classes.send(clazz)
- return None
-
-def _yield_until_matching_class(classes, needle):
- """Takes a class iterator and yields entries it until it reaches the class we're looking for.
-
- This relies on classes being sorted by package and class name."""
-
- for clazz in classes:
- if needle is None:
- yield clazz
- elif clazz.pkg.name < needle.pkg.name:
- # We haven't reached the right package yet
- yield clazz
- elif clazz.pkg.name == needle.pkg.name and clazz.fullname < needle.fullname:
- # We're in the right package, but not the right class yet
- yield clazz
- elif clazz.fullname == needle.fullname:
- # Class found, abort.
- return
- else:
- # We ran past the right class. Send it back into the iterator, then abort.
- classes.send(clazz)
- return
-
-class Failure():
- def __init__(self, sig, clazz, detail, error, rule, msg):
- self.clazz = clazz
- self.sig = sig
- self.error = error
- self.rule = rule
- self.msg = msg
-
- if error:
- self.head = "Error %s" % (rule) if rule else "Error"
- dump = "%s%s:%s %s" % (format(fg=RED, bg=BLACK, bold=True), self.head, format(reset=True), msg)
- else:
- self.head = "Warning %s" % (rule) if rule else "Warning"
- dump = "%s%s:%s %s" % (format(fg=YELLOW, bg=BLACK, bold=True), self.head, format(reset=True), msg)
-
- self.line = clazz.line
- blame = clazz.blame
- if detail is not None:
- dump += "\n in " + repr(detail)
- self.line = detail.line
- blame = detail.blame
- dump += "\n in " + repr(clazz)
- dump += "\n in " + repr(clazz.pkg)
- dump += "\n at line " + repr(self.line)
- if blame is not None:
- dump += "\n last modified by %s in %s" % (blame[1], blame[0])
-
- self.dump = dump
-
- def __repr__(self):
- return self.dump
-
-
-failures = {}
-
-def _fail(clazz, detail, error, rule, msg):
- """Records an API failure to be processed later."""
- global failures
-
- sig = "%s-%s-%s" % (clazz.fullname, detail.ident if detail else None, msg)
- sig = sig.replace(" deprecated ", " ")
-
- failures[sig] = Failure(sig, clazz, detail, error, rule, msg)
-
-
-def warn(clazz, detail, rule, msg):
- _fail(clazz, detail, False, rule, msg)
-
-def error(clazz, detail, rule, msg):
- _fail(clazz, detail, True, rule, msg)
-
-
-noticed = {}
-
-def notice(clazz):
- global noticed
-
- noticed[clazz.fullname] = hash(clazz)
-
-
-verifiers = {}
-
-def verifier(f):
- verifiers[f.__name__] = f
- return f
-
-
-@verifier
-def verify_constants(clazz):
- """All static final constants must be FOO_NAME style."""
- if re.match("android\.R\.[a-z]+", clazz.fullname): return
- if clazz.fullname.startswith("android.os.Build"): return
- if clazz.fullname == "android.system.OsConstants": return
-
- req = ["java.lang.String","byte","short","int","long","float","double","boolean","char"]
- for f in clazz.fields:
- if "static" in f.split and "final" in f.split:
- if re.match("[A-Z0-9_]+", f.name) is None:
- error(clazz, f, "C2", "Constant field names must be FOO_NAME")
- if f.typ != "java.lang.String":
- if f.name.startswith("MIN_") or f.name.startswith("MAX_"):
- warn(clazz, f, "C8", "If min/max could change in future, make them dynamic methods")
- if f.typ in req and f.value is None:
- error(clazz, f, None, "All constants must be defined at compile time")
-
-@verifier
-def verify_enums(clazz):
- """Enums are bad, mmkay?"""
- if clazz.extends == "java.lang.Enum" or "enum" in clazz.split:
- error(clazz, None, "F5", "Enums are not allowed")
-
-@verifier
-def verify_class_names(clazz):
- """Try catching malformed class names like myMtp or MTPUser."""
- if clazz.fullname.startswith("android.opengl"): return
- if clazz.fullname.startswith("android.renderscript"): return
- if re.match("android\.R\.[a-z]+", clazz.fullname): return
-
- if re.search("[A-Z]{2,}", clazz.name) is not None:
- warn(clazz, None, "S1", "Class names with acronyms should be Mtp not MTP")
- if re.match("[^A-Z]", clazz.name):
- error(clazz, None, "S1", "Class must start with uppercase char")
- if clazz.name.endswith("Impl"):
- error(clazz, None, None, "Don't expose your implementation details")
-
-
-@verifier
-def verify_method_names(clazz):
- """Try catching malformed method names, like Foo() or getMTU()."""
- if clazz.fullname.startswith("android.opengl"): return
- if clazz.fullname.startswith("android.renderscript"): return
- if clazz.fullname == "android.system.OsConstants": return
-
- for m in clazz.methods:
- if re.search("[A-Z]{2,}", m.name) is not None:
- warn(clazz, m, "S1", "Method names with acronyms should be getMtu() instead of getMTU()")
- if re.match("[^a-z]", m.name):
- error(clazz, m, "S1", "Method name must start with lowercase char")
-
-
-@verifier
-def verify_callbacks(clazz):
- """Verify Callback classes.
- All methods must follow onFoo() naming style."""
- if clazz.fullname == "android.speech.tts.SynthesisCallback": return
-
- if clazz.name.endswith("Callbacks"):
- error(clazz, None, "L1", "Callback class names should be singular")
- if clazz.name.endswith("Observer"):
- warn(clazz, None, "L1", "Class should be named FooCallback")
-
- if clazz.name.endswith("Callback"):
- for m in clazz.methods:
- if not re.match("on[A-Z][a-z]*", m.name):
- error(clazz, m, "L1", "Callback method names must be onFoo() style")
-
-
-@verifier
-def verify_listeners(clazz):
- """Verify Listener classes.
- All Listener classes must be interface.
- All methods must follow onFoo() naming style.
- If only a single method, it must match class name:
- interface OnFooListener { void onFoo() }"""
-
- if clazz.name.endswith("Listener"):
- if "abstract" in clazz.split and "class" in clazz.split:
- error(clazz, None, "L1", "Listeners should be an interface, or otherwise renamed Callback")
-
- for m in clazz.methods:
- if not re.match("on[A-Z][a-z]*", m.name):
- error(clazz, m, "L1", "Listener method names must be onFoo() style")
-
- if len(clazz.methods) == 1 and clazz.name.startswith("On"):
- m = clazz.methods[0]
- if (m.name + "Listener").lower() != clazz.name.lower():
- error(clazz, m, "L1", "Single listener method name must match class name")
-
-
-@verifier
-def verify_actions(clazz):
- """Verify intent actions.
- All action names must be named ACTION_FOO.
- All action values must be scoped by package and match name:
- package android.foo {
- String ACTION_BAR = "android.foo.action.BAR";
- }"""
- for f in clazz.fields:
- if f.value is None: continue
- if f.name.startswith("EXTRA_"): continue
- if f.name == "SERVICE_INTERFACE" or f.name == "PROVIDER_INTERFACE": continue
- if "INTERACTION" in f.name: continue
-
- if "static" in f.split and "final" in f.split and f.typ == "java.lang.String":
- if "_ACTION" in f.name or "ACTION_" in f.name or ".action." in f.value.lower():
- if not f.name.startswith("ACTION_"):
- error(clazz, f, "C3", "Intent action constant name must be ACTION_FOO")
- else:
- if clazz.fullname == "android.content.Intent":
- prefix = "android.intent.action"
- elif clazz.fullname == "android.provider.Settings":
- prefix = "android.settings"
- elif clazz.fullname == "android.app.admin.DevicePolicyManager" or clazz.fullname == "android.app.admin.DeviceAdminReceiver":
- prefix = "android.app.action"
- else:
- prefix = clazz.pkg.name + ".action"
- expected = prefix + "." + f.name[7:]
- if f.value != expected:
- error(clazz, f, "C4", "Inconsistent action value; expected '%s'" % (expected))
-
-
-@verifier
-def verify_extras(clazz):
- """Verify intent extras.
- All extra names must be named EXTRA_FOO.
- All extra values must be scoped by package and match name:
- package android.foo {
- String EXTRA_BAR = "android.foo.extra.BAR";
- }"""
- if clazz.fullname == "android.app.Notification": return
- if clazz.fullname == "android.appwidget.AppWidgetManager": return
-
- for f in clazz.fields:
- if f.value is None: continue
- if f.name.startswith("ACTION_"): continue
-
- if "static" in f.split and "final" in f.split and f.typ == "java.lang.String":
- if "_EXTRA" in f.name or "EXTRA_" in f.name or ".extra" in f.value.lower():
- if not f.name.startswith("EXTRA_"):
- error(clazz, f, "C3", "Intent extra must be EXTRA_FOO")
- else:
- if clazz.pkg.name == "android.content" and clazz.name == "Intent":
- prefix = "android.intent.extra"
- elif clazz.pkg.name == "android.app.admin":
- prefix = "android.app.extra"
- else:
- prefix = clazz.pkg.name + ".extra"
- expected = prefix + "." + f.name[6:]
- if f.value != expected:
- error(clazz, f, "C4", "Inconsistent extra value; expected '%s'" % (expected))
-
-
-@verifier
-def verify_equals(clazz):
- """Verify that equals() and hashCode() must be overridden together."""
- eq = False
- hc = False
- for m in clazz.methods:
- if "static" in m.split: continue
- if m.sig_matches("boolean", "equals", ["java.lang.Object"]): eq = True
- if m.sig_matches("int", "hashCode", []): hc = True
- if eq != hc:
- error(clazz, None, "M8", "Must override both equals and hashCode; missing one")
-
-
-@verifier
-def verify_parcelable(clazz):
- """Verify that Parcelable objects aren't hiding required bits."""
- if clazz.implements == "android.os.Parcelable":
- creator = [ i for i in clazz.fields if i.name == "CREATOR" ]
- write = [ i for i in clazz.methods if i.name == "writeToParcel" ]
- describe = [ i for i in clazz.methods if i.name == "describeContents" ]
-
- if len(creator) == 0 or len(write) == 0 or len(describe) == 0:
- error(clazz, None, "FW3", "Parcelable requires CREATOR, writeToParcel, and describeContents; missing one")
-
- if "final" not in clazz.split:
- error(clazz, None, "FW8", "Parcelable classes must be final")
-
- for c in clazz.ctors:
- if c.args == ["android.os.Parcel"]:
- error(clazz, c, "FW3", "Parcelable inflation is exposed through CREATOR, not raw constructors")
-
-
-@verifier
-def verify_protected(clazz):
- """Verify that no protected methods or fields are allowed."""
- for m in clazz.methods:
- if m.name == "finalize": continue
- if "protected" in m.split:
- error(clazz, m, "M7", "Protected methods not allowed; must be public")
- for f in clazz.fields:
- if "protected" in f.split:
- error(clazz, f, "M7", "Protected fields not allowed; must be public")
-
-
-@verifier
-def verify_fields(clazz):
- """Verify that all exposed fields are final.
- Exposed fields must follow myName style.
- Catch internal mFoo objects being exposed."""
-
- IGNORE_BARE_FIELDS = [
- "android.app.ActivityManager.RecentTaskInfo",
- "android.app.Notification",
- "android.content.pm.ActivityInfo",
- "android.content.pm.ApplicationInfo",
- "android.content.pm.ComponentInfo",
- "android.content.pm.ResolveInfo",
- "android.content.pm.FeatureGroupInfo",
- "android.content.pm.InstrumentationInfo",
- "android.content.pm.PackageInfo",
- "android.content.pm.PackageItemInfo",
- "android.content.res.Configuration",
- "android.graphics.BitmapFactory.Options",
- "android.os.Message",
- "android.system.StructPollfd",
- ]
-
- for f in clazz.fields:
- if not "final" in f.split:
- if clazz.fullname in IGNORE_BARE_FIELDS:
- pass
- elif clazz.fullname.endswith("LayoutParams"):
- pass
- elif clazz.fullname.startswith("android.util.Mutable"):
- pass
- else:
- error(clazz, f, "F2", "Bare fields must be marked final, or add accessors if mutable")
-
- if "static" not in f.split and "property" not in f.split:
- if not re.match("[a-z]([a-zA-Z]+)?", f.name):
- error(clazz, f, "S1", "Non-static fields must be named using myField style")
-
- if re.match("[ms][A-Z]", f.name):
- error(clazz, f, "F1", "Internal objects must not be exposed")
-
- if re.match("[A-Z_]+", f.name):
- if "static" not in f.split or "final" not in f.split:
- error(clazz, f, "C2", "Constants must be marked static final")
-
-
-@verifier
-def verify_register(clazz):
- """Verify parity of registration methods.
- Callback objects use register/unregister methods.
- Listener objects use add/remove methods."""
- methods = [ m.name for m in clazz.methods ]
- for m in clazz.methods:
- if "Callback" in m.raw:
- if m.name.startswith("register"):
- other = "unregister" + m.name[8:]
- if other not in methods:
- error(clazz, m, "L2", "Missing unregister method")
- if m.name.startswith("unregister"):
- other = "register" + m.name[10:]
- if other not in methods:
- error(clazz, m, "L2", "Missing register method")
-
- if m.name.startswith("add") or m.name.startswith("remove"):
- error(clazz, m, "L3", "Callback methods should be named register/unregister")
-
- if "Listener" in m.raw:
- if m.name.startswith("add"):
- other = "remove" + m.name[3:]
- if other not in methods:
- error(clazz, m, "L2", "Missing remove method")
- if m.name.startswith("remove") and not m.name.startswith("removeAll"):
- other = "add" + m.name[6:]
- if other not in methods:
- error(clazz, m, "L2", "Missing add method")
-
- if m.name.startswith("register") or m.name.startswith("unregister"):
- error(clazz, m, "L3", "Listener methods should be named add/remove")
-
-
-@verifier
-def verify_sync(clazz):
- """Verify synchronized methods aren't exposed."""
- for m in clazz.methods:
- if "synchronized" in m.split:
- error(clazz, m, "M5", "Internal locks must not be exposed")
-
-
-@verifier
-def verify_intent_builder(clazz):
- """Verify that Intent builders are createFooIntent() style."""
- if clazz.name == "Intent": return
-
- for m in clazz.methods:
- if m.typ == "android.content.Intent":
- if m.name.startswith("create") and m.name.endswith("Intent"):
- pass
- else:
- warn(clazz, m, "FW1", "Methods creating an Intent should be named createFooIntent()")
-
-
-@verifier
-def verify_helper_classes(clazz):
- """Verify that helper classes are named consistently with what they extend.
- All developer extendable methods should be named onFoo()."""
- test_methods = False
- if clazz.extends == "android.app.Service":
- test_methods = True
- if not clazz.name.endswith("Service"):
- error(clazz, None, "CL4", "Inconsistent class name; should be FooService")
-
- found = False
- for f in clazz.fields:
- if f.name == "SERVICE_INTERFACE":
- found = True
- if f.value != clazz.fullname:
- error(clazz, f, "C4", "Inconsistent interface constant; expected '%s'" % (clazz.fullname))
-
- if clazz.extends == "android.content.ContentProvider":
- test_methods = True
- if not clazz.name.endswith("Provider"):
- error(clazz, None, "CL4", "Inconsistent class name; should be FooProvider")
-
- found = False
- for f in clazz.fields:
- if f.name == "PROVIDER_INTERFACE":
- found = True
- if f.value != clazz.fullname:
- error(clazz, f, "C4", "Inconsistent interface constant; expected '%s'" % (clazz.fullname))
-
- if clazz.extends == "android.content.BroadcastReceiver":
- test_methods = True
- if not clazz.name.endswith("Receiver"):
- error(clazz, None, "CL4", "Inconsistent class name; should be FooReceiver")
-
- if clazz.extends == "android.app.Activity":
- test_methods = True
- if not clazz.name.endswith("Activity"):
- error(clazz, None, "CL4", "Inconsistent class name; should be FooActivity")
-
- if test_methods:
- for m in clazz.methods:
- if "final" in m.split: continue
- if not re.match("on[A-Z]", m.name):
- if "abstract" in m.split:
- warn(clazz, m, None, "Methods implemented by developers should be named onFoo()")
- else:
- warn(clazz, m, None, "If implemented by developer, should be named onFoo(); otherwise consider marking final")
-
-
-@verifier
-def verify_builder(clazz):
- """Verify builder classes.
- Methods should return the builder to enable chaining."""
- if clazz.extends: return
- if not clazz.name.endswith("Builder"): return
-
- if clazz.name != "Builder":
- warn(clazz, None, None, "Builder should be defined as inner class")
-
- has_build = False
- for m in clazz.methods:
- if m.name == "build":
- has_build = True
- continue
-
- if m.name.startswith("get"): continue
- if m.name.startswith("clear"): continue
-
- if m.name.startswith("with"):
- warn(clazz, m, None, "Builder methods names should use setFoo() style")
-
- if m.name.startswith("set"):
- if not m.typ.endswith(clazz.fullname):
- warn(clazz, m, "M4", "Methods must return the builder object")
-
- if not has_build:
- warn(clazz, None, None, "Missing build() method")
-
- if "final" not in clazz.split:
- error(clazz, None, None, "Builder should be final")
-
-
-@verifier
-def verify_aidl(clazz):
- """Catch people exposing raw AIDL."""
- if clazz.extends == "android.os.Binder" or clazz.implements == "android.os.IInterface":
- error(clazz, None, None, "Raw AIDL interfaces must not be exposed")
-
-
-@verifier
-def verify_internal(clazz):
- """Catch people exposing internal classes."""
- if clazz.pkg.name.startswith("com.android"):
- error(clazz, None, None, "Internal classes must not be exposed")
-
-def layering_build_ranking(ranking_list):
- r = {}
- for rank, ps in enumerate(ranking_list):
- if not isinstance(ps, list):
- ps = [ps]
- for p in ps:
- rs = r
- for n in p.split('.'):
- if n not in rs:
- rs[n] = {}
- rs = rs[n]
- rs['-rank'] = rank
- return r
-
-LAYERING_PACKAGE_RANKING = layering_build_ranking([
- ["android.service","android.accessibilityservice","android.inputmethodservice","android.printservice","android.appwidget","android.webkit","android.preference","android.gesture","android.print"],
- "android.app",
- "android.widget",
- "android.view",
- "android.animation",
- "android.provider",
- ["android.content","android.graphics.drawable"],
- "android.database",
- "android.text",
- "android.graphics",
- "android.os",
- "android.util"
-])
-
-@verifier
-def verify_layering(clazz):
- """Catch package layering violations.
- For example, something in android.os depending on android.app."""
-
- def rank(p):
- r = None
- l = LAYERING_PACKAGE_RANKING
- for n in p.split('.'):
- if n in l:
- l = l[n]
- if '-rank' in l:
- r = l['-rank']
- else:
- break
- return r
-
- cr = rank(clazz.pkg.name)
- if cr is None: return
-
- for f in clazz.fields:
- ir = rank(f.typ)
- if ir is not None and ir < cr:
- warn(clazz, f, "FW6", "Field type violates package layering")
-
- for m in itertools.chain(clazz.methods, clazz.ctors):
- ir = rank(m.typ)
- if ir is not None and ir < cr:
- warn(clazz, m, "FW6", "Method return type violates package layering")
- for arg in m.args:
- ir = rank(arg)
- if ir is not None and ir < cr:
- warn(clazz, m, "FW6", "Method argument type violates package layering")
-
-
-@verifier
-def verify_boolean(clazz):
- """Verifies that boolean accessors are named correctly.
- For example, hasFoo() and setHasFoo()."""
-
- def is_get(m): return len(m.args) == 0 and m.typ == "boolean"
- def is_set(m): return len(m.args) == 1 and m.args[0] == "boolean"
-
- gets = [ m for m in clazz.methods if is_get(m) ]
- sets = [ m for m in clazz.methods if is_set(m) ]
-
- def error_if_exists(methods, trigger, expected, actual):
- for m in methods:
- if m.name == actual:
- error(clazz, m, "M6", "Symmetric method for %s must be named %s" % (trigger, expected))
-
- for m in clazz.methods:
- if is_get(m):
- if re.match("is[A-Z]", m.name):
- target = m.name[2:]
- expected = "setIs" + target
- error_if_exists(sets, m.name, expected, "setHas" + target)
- elif re.match("has[A-Z]", m.name):
- target = m.name[3:]
- expected = "setHas" + target
- error_if_exists(sets, m.name, expected, "setIs" + target)
- error_if_exists(sets, m.name, expected, "set" + target)
- elif re.match("get[A-Z]", m.name):
- target = m.name[3:]
- expected = "set" + target
- error_if_exists(sets, m.name, expected, "setIs" + target)
- error_if_exists(sets, m.name, expected, "setHas" + target)
-
- if is_set(m):
- if re.match("set[A-Z]", m.name):
- target = m.name[3:]
- expected = "get" + target
- error_if_exists(sets, m.name, expected, "is" + target)
- error_if_exists(sets, m.name, expected, "has" + target)
-
-
-@verifier
-def verify_collections(clazz):
- """Verifies that collection types are interfaces."""
- if clazz.fullname == "android.os.Bundle": return
- if clazz.fullname == "android.os.Parcel": return
-
- bad = ["java.util.Vector", "java.util.LinkedList", "java.util.ArrayList", "java.util.Stack",
- "java.util.HashMap", "java.util.HashSet", "android.util.ArraySet", "android.util.ArrayMap"]
- for m in clazz.methods:
- if m.typ in bad:
- error(clazz, m, "CL2", "Return type is concrete collection; must be higher-level interface")
- for arg in m.args:
- if arg in bad:
- error(clazz, m, "CL2", "Argument is concrete collection; must be higher-level interface")
-
-
-@verifier
-def verify_uris(clazz):
- bad = ["java.net.URL", "java.net.URI", "android.net.URL"]
-
- for f in clazz.fields:
- if f.typ in bad:
- error(clazz, f, None, "Field must be android.net.Uri instead of " + f.typ)
-
- for m in clazz.methods + clazz.ctors:
- if m.typ in bad:
- error(clazz, m, None, "Must return android.net.Uri instead of " + m.typ)
- for arg in m.args:
- if arg in bad:
- error(clazz, m, None, "Argument must take android.net.Uri instead of " + arg)
-
-
-@verifier
-def verify_flags(clazz):
- """Verifies that flags are non-overlapping."""
- known = collections.defaultdict(int)
- for f in clazz.fields:
- if "FLAG_" in f.name:
- try:
- val = int(f.value)
- except:
- continue
-
- scope = f.name[0:f.name.index("FLAG_")]
- if val & known[scope]:
- warn(clazz, f, "C1", "Found overlapping flag constant value")
- known[scope] |= val
-
-
-@verifier
-def verify_exception(clazz):
- """Verifies that methods don't throw generic exceptions."""
- for m in clazz.methods:
- for t in m.throws:
- if t in ["java.lang.Exception", "java.lang.Throwable", "java.lang.Error"]:
- error(clazz, m, "S1", "Methods must not throw generic exceptions")
-
- if t in ["android.os.RemoteException"]:
- if clazz.fullname == "android.content.ContentProviderClient": continue
- if clazz.fullname == "android.os.Binder": continue
- if clazz.fullname == "android.os.IBinder": continue
-
- error(clazz, m, "FW9", "Methods calling into system server should rethrow RemoteException as RuntimeException")
-
- if len(m.args) == 0 and t in ["java.lang.IllegalArgumentException", "java.lang.NullPointerException"]:
- warn(clazz, m, "S1", "Methods taking no arguments should throw IllegalStateException")
-
-
-GOOGLE_IGNORECASE = re.compile("google", re.IGNORECASE)
-
-# Not marked as @verifier, because it is only conditionally applied.
-def verify_google(clazz):
- """Verifies that APIs never reference Google."""
-
- if GOOGLE_IGNORECASE.search(clazz.raw) is not None:
- error(clazz, None, None, "Must never reference Google")
-
- for test in clazz.ctors, clazz.fields, clazz.methods:
- for t in test:
- if GOOGLE_IGNORECASE.search(t.raw) is not None:
- error(clazz, t, None, "Must never reference Google")
-
-
-@verifier
-def verify_bitset(clazz):
- """Verifies that we avoid using heavy BitSet."""
-
- for f in clazz.fields:
- if f.typ == "java.util.BitSet":
- error(clazz, f, None, "Field type must not be heavy BitSet")
-
- for m in clazz.methods:
- if m.typ == "java.util.BitSet":
- error(clazz, m, None, "Return type must not be heavy BitSet")
- for arg in m.args:
- if arg == "java.util.BitSet":
- error(clazz, m, None, "Argument type must not be heavy BitSet")
-
-
-@verifier
-def verify_manager(clazz):
- """Verifies that FooManager is only obtained from Context."""
-
- if not clazz.name.endswith("Manager"): return
-
- for c in clazz.ctors:
- error(clazz, c, None, "Managers must always be obtained from Context; no direct constructors")
-
- for m in clazz.methods:
- if m.typ == clazz.fullname:
- error(clazz, m, None, "Managers must always be obtained from Context")
-
-
-@verifier
-def verify_boxed(clazz):
- """Verifies that methods avoid boxed primitives."""
-
- boxed = ["java.lang.Number","java.lang.Byte","java.lang.Double","java.lang.Float","java.lang.Integer","java.lang.Long","java.lang.Short"]
-
- for c in clazz.ctors:
- for arg in c.args:
- if arg in boxed:
- error(clazz, c, "M11", "Must avoid boxed primitives")
-
- for f in clazz.fields:
- if f.typ in boxed:
- error(clazz, f, "M11", "Must avoid boxed primitives")
-
- for m in clazz.methods:
- if m.typ in boxed:
- error(clazz, m, "M11", "Must avoid boxed primitives")
- for arg in m.args:
- if arg in boxed:
- error(clazz, m, "M11", "Must avoid boxed primitives")
-
-
-@verifier
-def verify_static_utils(clazz):
- """Verifies that helper classes can't be constructed."""
- if clazz.fullname.startswith("android.opengl"): return
- if clazz.fullname.startswith("android.R"): return
-
- # Only care about classes with default constructors
- if len(clazz.ctors) == 1 and len(clazz.ctors[0].args) == 0:
- test = []
- test.extend(clazz.fields)
- test.extend(clazz.methods)
-
- if len(test) == 0: return
- for t in test:
- if "static" not in t.split:
- return
-
- error(clazz, None, None, "Fully-static utility classes must not have constructor")
-
-
-# @verifier # Disabled for now
-def verify_overload_args(clazz):
- """Verifies that method overloads add new arguments at the end."""
- if clazz.fullname.startswith("android.opengl"): return
-
- overloads = collections.defaultdict(list)
- for m in clazz.methods:
- if "deprecated" in m.split: continue
- overloads[m.name].append(m)
-
- for name, methods in overloads.items():
- if len(methods) <= 1: continue
-
- # Look for arguments common across all overloads
- def cluster(args):
- count = collections.defaultdict(int)
- res = set()
- for i in range(len(args)):
- a = args[i]
- res.add("%s#%d" % (a, count[a]))
- count[a] += 1
- return res
-
- common_args = cluster(methods[0].args)
- for m in methods:
- common_args = common_args & cluster(m.args)
-
- if len(common_args) == 0: continue
-
- # Require that all common arguments are present at start of signature
- locked_sig = None
- for m in methods:
- sig = m.args[0:len(common_args)]
- if not common_args.issubset(cluster(sig)):
- warn(clazz, m, "M2", "Expected common arguments [%s] at beginning of overloaded method" % (", ".join(common_args)))
- elif not locked_sig:
- locked_sig = sig
- elif locked_sig != sig:
- error(clazz, m, "M2", "Expected consistent argument ordering between overloads: %s..." % (", ".join(locked_sig)))
-
-
-@verifier
-def verify_callback_handlers(clazz):
- """Verifies that methods adding listener/callback have overload
- for specifying delivery thread."""
-
- # Ignore UI packages which assume main thread
- skip = [
- "animation",
- "view",
- "graphics",
- "transition",
- "widget",
- "webkit",
- ]
- for s in skip:
- if s in clazz.pkg.name_path: return
- if s in clazz.extends_path: return
-
- # Ignore UI classes which assume main thread
- if "app" in clazz.pkg.name_path or "app" in clazz.extends_path:
- for s in ["ActionBar","Dialog","Application","Activity","Fragment","Loader"]:
- if s in clazz.fullname: return
- if "content" in clazz.pkg.name_path or "content" in clazz.extends_path:
- for s in ["Loader"]:
- if s in clazz.fullname: return
-
- found = {}
- by_name = collections.defaultdict(list)
- examine = clazz.ctors + clazz.methods
- for m in examine:
- if m.name.startswith("unregister"): continue
- if m.name.startswith("remove"): continue
- if re.match("on[A-Z]+", m.name): continue
-
- by_name[m.name].append(m)
-
- for a in m.args:
- if a.endswith("Listener") or a.endswith("Callback") or a.endswith("Callbacks"):
- found[m.name] = m
-
- for f in found.values():
- takes_handler = False
- takes_exec = False
- for m in by_name[f.name]:
- if "android.os.Handler" in m.args:
- takes_handler = True
- if "java.util.concurrent.Executor" in m.args:
- takes_exec = True
- if not takes_exec:
- warn(clazz, f, "L1", "Registration methods should have overload that accepts delivery Executor")
-
-
-@verifier
-def verify_context_first(clazz):
- """Verifies that methods accepting a Context keep it the first argument."""
- examine = clazz.ctors + clazz.methods
- for m in examine:
- if len(m.args) > 1 and m.args[0] != "android.content.Context":
- if "android.content.Context" in m.args[1:]:
- error(clazz, m, "M3", "Context is distinct, so it must be the first argument")
- if len(m.args) > 1 and m.args[0] != "android.content.ContentResolver":
- if "android.content.ContentResolver" in m.args[1:]:
- error(clazz, m, "M3", "ContentResolver is distinct, so it must be the first argument")
-
-
-@verifier
-def verify_listener_last(clazz):
- """Verifies that methods accepting a Listener or Callback keep them as last arguments."""
- examine = clazz.ctors + clazz.methods
- for m in examine:
- if "Listener" in m.name or "Callback" in m.name: continue
- found = False
- for a in m.args:
- if a.endswith("Callback") or a.endswith("Callbacks") or a.endswith("Listener"):
- found = True
- elif found:
- warn(clazz, m, "M3", "Listeners should always be at end of argument list")
-
-
-@verifier
-def verify_resource_names(clazz):
- """Verifies that resource names have consistent case."""
- if not re.match("android\.R\.[a-z]+", clazz.fullname): return
-
- # Resources defined by files are foo_bar_baz
- if clazz.name in ["anim","animator","color","dimen","drawable","interpolator","layout","transition","menu","mipmap","string","plurals","raw","xml"]:
- for f in clazz.fields:
- if re.match("config_[a-z][a-zA-Z1-9]*$", f.name): continue
- if f.name.startswith("config_"):
- error(clazz, f, None, "Expected config name to be config_fooBarBaz style")
-
- if re.match("[a-z1-9_]+$", f.name): continue
- error(clazz, f, None, "Expected resource name in this class to be foo_bar_baz style")
-
- # Resources defined inside files are fooBarBaz
- if clazz.name in ["array","attr","id","bool","fraction","integer"]:
- for f in clazz.fields:
- if re.match("config_[a-z][a-zA-Z1-9]*$", f.name): continue
- if re.match("layout_[a-z][a-zA-Z1-9]*$", f.name): continue
- if re.match("state_[a-z_]*$", f.name): continue
-
- if re.match("[a-z][a-zA-Z1-9]*$", f.name): continue
- error(clazz, f, "C7", "Expected resource name in this class to be fooBarBaz style")
-
- # Styles are FooBar_Baz
- if clazz.name in ["style"]:
- for f in clazz.fields:
- if re.match("[A-Z][A-Za-z1-9]+(_[A-Z][A-Za-z1-9]+?)*$", f.name): continue
- error(clazz, f, "C7", "Expected resource name in this class to be FooBar_Baz style")
-
-
-@verifier
-def verify_files(clazz):
- """Verifies that methods accepting File also accept streams."""
-
- has_file = set()
- has_stream = set()
-
- test = []
- test.extend(clazz.ctors)
- test.extend(clazz.methods)
-
- for m in test:
- if "java.io.File" in m.args:
- has_file.add(m)
- if "java.io.FileDescriptor" in m.args or "android.os.ParcelFileDescriptor" in m.args or "java.io.InputStream" in m.args or "java.io.OutputStream" in m.args:
- has_stream.add(m.name)
-
- for m in has_file:
- if m.name not in has_stream:
- warn(clazz, m, "M10", "Methods accepting File should also accept FileDescriptor or streams")
-
-
-@verifier
-def verify_manager_list(clazz):
- """Verifies that managers return List<? extends Parcelable> instead of arrays."""
-
- if not clazz.name.endswith("Manager"): return
-
- for m in clazz.methods:
- if m.typ.startswith("android.") and m.typ.endswith("[]"):
- warn(clazz, m, None, "Methods should return List<? extends Parcelable> instead of Parcelable[] to support ParceledListSlice under the hood")
-
-
-@verifier
-def verify_abstract_inner(clazz):
- """Verifies that abstract inner classes are static."""
-
- if re.match(".+?\.[A-Z][^\.]+\.[A-Z]", clazz.fullname):
- if "abstract" in clazz.split and "static" not in clazz.split:
- warn(clazz, None, None, "Abstract inner classes should be static to improve testability")
-
-
-@verifier
-def verify_runtime_exceptions(clazz):
- """Verifies that runtime exceptions aren't listed in throws."""
-
- banned = [
- "java.lang.NullPointerException",
- "java.lang.ClassCastException",
- "java.lang.IndexOutOfBoundsException",
- "java.lang.reflect.UndeclaredThrowableException",
- "java.lang.reflect.MalformedParametersException",
- "java.lang.reflect.MalformedParameterizedTypeException",
- "java.lang.invoke.WrongMethodTypeException",
- "java.lang.EnumConstantNotPresentException",
- "java.lang.IllegalMonitorStateException",
- "java.lang.SecurityException",
- "java.lang.UnsupportedOperationException",
- "java.lang.annotation.AnnotationTypeMismatchException",
- "java.lang.annotation.IncompleteAnnotationException",
- "java.lang.TypeNotPresentException",
- "java.lang.IllegalStateException",
- "java.lang.ArithmeticException",
- "java.lang.IllegalArgumentException",
- "java.lang.ArrayStoreException",
- "java.lang.NegativeArraySizeException",
- "java.util.MissingResourceException",
- "java.util.EmptyStackException",
- "java.util.concurrent.CompletionException",
- "java.util.concurrent.RejectedExecutionException",
- "java.util.IllformedLocaleException",
- "java.util.ConcurrentModificationException",
- "java.util.NoSuchElementException",
- "java.io.UncheckedIOException",
- "java.time.DateTimeException",
- "java.security.ProviderException",
- "java.nio.BufferUnderflowException",
- "java.nio.BufferOverflowException",
- ]
-
- examine = clazz.ctors + clazz.methods
- for m in examine:
- for t in m.throws:
- if t in banned:
- error(clazz, m, None, "Methods must not mention RuntimeException subclasses in throws clauses")
-
-
-@verifier
-def verify_error(clazz):
- """Verifies that we always use Exception instead of Error."""
- if not clazz.extends: return
- if clazz.extends.endswith("Error"):
- error(clazz, None, None, "Trouble must be reported through an Exception, not Error")
- if clazz.extends.endswith("Exception") and not clazz.name.endswith("Exception"):
- error(clazz, None, None, "Exceptions must be named FooException")
-
-
-@verifier
-def verify_units(clazz):
- """Verifies that we use consistent naming for units."""
-
- # If we find K, recommend replacing with V
- bad = {
- "Ns": "Nanos",
- "Ms": "Millis or Micros",
- "Sec": "Seconds", "Secs": "Seconds",
- "Hr": "Hours", "Hrs": "Hours",
- "Mo": "Months", "Mos": "Months",
- "Yr": "Years", "Yrs": "Years",
- "Byte": "Bytes", "Space": "Bytes",
- }
-
- for m in clazz.methods:
- if m.typ not in ["short","int","long"]: continue
- for k, v in bad.iteritems():
- if m.name.endswith(k):
- error(clazz, m, None, "Expected method name units to be " + v)
- if m.name.endswith("Nanos") or m.name.endswith("Micros"):
- warn(clazz, m, None, "Returned time values are strongly encouraged to be in milliseconds unless you need the extra precision")
- if m.name.endswith("Seconds"):
- error(clazz, m, None, "Returned time values must be in milliseconds")
-
- for m in clazz.methods:
- typ = m.typ
- if typ == "void":
- if len(m.args) != 1: continue
- typ = m.args[0]
-
- if m.name.endswith("Fraction") and typ != "float":
- error(clazz, m, None, "Fractions must use floats")
- if m.name.endswith("Percentage") and typ != "int":
- error(clazz, m, None, "Percentage must use ints")
-
-
-@verifier
-def verify_closable(clazz):
- """Verifies that classes are AutoClosable."""
- if "java.lang.AutoCloseable" in clazz.implements_all: return
- if "java.io.Closeable" in clazz.implements_all: return
-
- for m in clazz.methods:
- if len(m.args) > 0: continue
- if m.name in ["close","release","destroy","finish","finalize","disconnect","shutdown","stop","free","quit"]:
- warn(clazz, m, None, "Classes that release resources should implement AutoClosable and CloseGuard")
- return
-
-
-@verifier
-def verify_member_name_not_kotlin_keyword(clazz):
- """Prevent method names which are keywords in Kotlin."""
-
- # https://kotlinlang.org/docs/reference/keyword-reference.html#hard-keywords
- # This list does not include Java keywords as those are already impossible to use.
- keywords = [
- 'as',
- 'fun',
- 'in',
- 'is',
- 'object',
- 'typealias',
- 'val',
- 'var',
- 'when',
- ]
-
- for m in clazz.methods:
- if m.name in keywords:
- error(clazz, m, None, "Method name must not be a Kotlin keyword")
- for f in clazz.fields:
- if f.name in keywords:
- error(clazz, f, None, "Field name must not be a Kotlin keyword")
-
-
-@verifier
-def verify_method_name_not_kotlin_operator(clazz):
- """Warn about method names which become operators in Kotlin."""
-
- binary = set()
-
- def unique_binary_op(m, op):
- if op in binary:
- error(clazz, m, None, "Only one of '{0}' and '{0}Assign' methods should be present for Kotlin".format(op))
- binary.add(op)
-
- for m in clazz.methods:
- if 'static' in m.split or 'operator' in m.split:
- continue
-
- # https://kotlinlang.org/docs/reference/operator-overloading.html#unary-prefix-operators
- if m.name in ['unaryPlus', 'unaryMinus', 'not'] and len(m.args) == 0:
- warn(clazz, m, None, "Method can be invoked as a unary operator from Kotlin")
-
- # https://kotlinlang.org/docs/reference/operator-overloading.html#increments-and-decrements
- if m.name in ['inc', 'dec'] and len(m.args) == 0 and m.typ != 'void':
- # This only applies if the return type is the same or a subtype of the enclosing class, but we have no
- # practical way of checking that relationship here.
- warn(clazz, m, None, "Method can be invoked as a pre/postfix inc/decrement operator from Kotlin")
-
- # https://kotlinlang.org/docs/reference/operator-overloading.html#arithmetic
- if m.name in ['plus', 'minus', 'times', 'div', 'rem', 'mod', 'rangeTo'] and len(m.args) == 1:
- warn(clazz, m, None, "Method can be invoked as a binary operator from Kotlin")
- unique_binary_op(m, m.name)
-
- # https://kotlinlang.org/docs/reference/operator-overloading.html#in
- if m.name == 'contains' and len(m.args) == 1 and m.typ == 'boolean':
- warn(clazz, m, None, "Method can be invoked as a 'in' operator from Kotlin")
-
- # https://kotlinlang.org/docs/reference/operator-overloading.html#indexed
- if (m.name == 'get' and len(m.args) > 0) or (m.name == 'set' and len(m.args) > 1):
- warn(clazz, m, None, "Method can be invoked with an indexing operator from Kotlin")
-
- # https://kotlinlang.org/docs/reference/operator-overloading.html#invoke
- if m.name == 'invoke':
- warn(clazz, m, None, "Method can be invoked with function call syntax from Kotlin")
-
- # https://kotlinlang.org/docs/reference/operator-overloading.html#assignments
- if m.name in ['plusAssign', 'minusAssign', 'timesAssign', 'divAssign', 'remAssign', 'modAssign'] \
- and len(m.args) == 1 \
- and m.typ == 'void':
- warn(clazz, m, None, "Method can be invoked as a compound assignment operator from Kotlin")
- unique_binary_op(m, m.name[:-6]) # Remove 'Assign' suffix
-
-
-@verifier
-def verify_collections_over_arrays(clazz):
- """Warn that [] should be Collections."""
-
- if "@interface" in clazz.split:
- return
-
- safe = ["java.lang.String[]","byte[]","short[]","int[]","long[]","float[]","double[]","boolean[]","char[]"]
- for m in clazz.methods:
- if m.typ.endswith("[]") and m.typ not in safe:
- warn(clazz, m, None, "Method should return Collection<> (or subclass) instead of raw array")
- for arg in m.args:
- if arg.endswith("[]") and arg not in safe:
- warn(clazz, m, None, "Method argument should be Collection<> (or subclass) instead of raw array")
-
-
-@verifier
-def verify_user_handle(clazz):
- """Methods taking UserHandle should be ForUser or AsUser."""
- if clazz.name.endswith("Listener") or clazz.name.endswith("Callback") or clazz.name.endswith("Callbacks"): return
- if clazz.fullname == "android.app.admin.DeviceAdminReceiver": return
- if clazz.fullname == "android.content.pm.LauncherApps": return
- if clazz.fullname == "android.os.UserHandle": return
- if clazz.fullname == "android.os.UserManager": return
-
- for m in clazz.methods:
- if re.match("on[A-Z]+", m.name): continue
-
- has_arg = "android.os.UserHandle" in m.args
- has_name = m.name.endswith("AsUser") or m.name.endswith("ForUser")
-
- if clazz.fullname.endswith("Manager") and has_arg:
- warn(clazz, m, None, "When a method overload is needed to target a specific "
- "UserHandle, callers should be directed to use "
- "Context.createPackageContextAsUser() and re-obtain the relevant "
- "Manager, and no new API should be added")
- elif has_arg and not has_name:
- warn(clazz, m, None, "Method taking UserHandle should be named 'doFooAsUser' "
- "or 'queryFooForUser'")
-
-
-@verifier
-def verify_params(clazz):
- """Parameter classes should be 'Params'."""
- if clazz.name.endswith("Params"): return
- if clazz.fullname == "android.app.ActivityOptions": return
- if clazz.fullname == "android.app.BroadcastOptions": return
- if clazz.fullname == "android.os.Bundle": return
- if clazz.fullname == "android.os.BaseBundle": return
- if clazz.fullname == "android.os.PersistableBundle": return
-
- bad = ["Param","Parameter","Parameters","Args","Arg","Argument","Arguments","Options","Bundle"]
- for b in bad:
- if clazz.name.endswith(b):
- error(clazz, None, None, "Classes holding a set of parameters should be called 'FooParams'")
-
-
-@verifier
-def verify_services(clazz):
- """Service name should be FOO_BAR_SERVICE = 'foo_bar'."""
- if clazz.fullname != "android.content.Context": return
-
- for f in clazz.fields:
- if f.typ != "java.lang.String": continue
- found = re.match(r"([A-Z_]+)_SERVICE", f.name)
- if found:
- expected = found.group(1).lower()
- if f.value != expected:
- error(clazz, f, "C4", "Inconsistent service value; expected '%s'" % (expected))
-
-
-@verifier
-def verify_tense(clazz):
- """Verify tenses of method names."""
- if clazz.fullname.startswith("android.opengl"): return
-
- for m in clazz.methods:
- if m.name.endswith("Enable"):
- warn(clazz, m, None, "Unexpected tense; probably meant 'enabled'")
-
-
-@verifier
-def verify_icu(clazz):
- """Verifies that richer ICU replacements are used."""
- better = {
- "java.util.TimeZone": "android.icu.util.TimeZone",
- "java.util.Calendar": "android.icu.util.Calendar",
- "java.util.Locale": "android.icu.util.ULocale",
- "java.util.ResourceBundle": "android.icu.util.UResourceBundle",
- "java.util.SimpleTimeZone": "android.icu.util.SimpleTimeZone",
- "java.util.StringTokenizer": "android.icu.util.StringTokenizer",
- "java.util.GregorianCalendar": "android.icu.util.GregorianCalendar",
- "java.lang.Character": "android.icu.lang.UCharacter",
- "java.text.BreakIterator": "android.icu.text.BreakIterator",
- "java.text.Collator": "android.icu.text.Collator",
- "java.text.DecimalFormatSymbols": "android.icu.text.DecimalFormatSymbols",
- "java.text.NumberFormat": "android.icu.text.NumberFormat",
- "java.text.DateFormatSymbols": "android.icu.text.DateFormatSymbols",
- "java.text.DateFormat": "android.icu.text.DateFormat",
- "java.text.SimpleDateFormat": "android.icu.text.SimpleDateFormat",
- "java.text.MessageFormat": "android.icu.text.MessageFormat",
- "java.text.DecimalFormat": "android.icu.text.DecimalFormat",
- }
-
- for m in clazz.ctors + clazz.methods:
- types = []
- types.extend(m.typ)
- types.extend(m.args)
- for arg in types:
- if arg in better:
- warn(clazz, m, None, "Type %s should be replaced with richer ICU type %s" % (arg, better[arg]))
-
-
-@verifier
-def verify_clone(clazz):
- """Verify that clone() isn't implemented; see EJ page 61."""
- for m in clazz.methods:
- if m.name == "clone":
- error(clazz, m, None, "Provide an explicit copy constructor instead of implementing clone()")
-
-
-@verifier
-def verify_pfd(clazz):
- """Verify that android APIs use PFD over FD."""
- if clazz.fullname == "android.os.FileUtils" or clazz.fullname == "android.system.Os":
- return
-
- examine = clazz.ctors + clazz.methods
- for m in examine:
- if m.typ == "java.io.FileDescriptor":
- error(clazz, m, "FW11", "Must use ParcelFileDescriptor")
- if m.typ == "int":
- if "Fd" in m.name or "FD" in m.name or "FileDescriptor" in m.name:
- error(clazz, m, "FW11", "Must use ParcelFileDescriptor")
- for arg in m.args:
- if arg == "java.io.FileDescriptor":
- error(clazz, m, "FW11", "Must use ParcelFileDescriptor")
-
- for f in clazz.fields:
- if f.typ == "java.io.FileDescriptor":
- error(clazz, f, "FW11", "Must use ParcelFileDescriptor")
-
-
-@verifier
-def verify_numbers(clazz):
- """Discourage small numbers types like short and byte."""
-
- discouraged = ["short","byte"]
-
- for c in clazz.ctors:
- for arg in c.args:
- if arg in discouraged:
- warn(clazz, c, "FW12", "Should avoid odd sized primitives; use int instead")
-
- for f in clazz.fields:
- if f.typ in discouraged:
- warn(clazz, f, "FW12", "Should avoid odd sized primitives; use int instead")
-
- for m in clazz.methods:
- if m.typ in discouraged:
- warn(clazz, m, "FW12", "Should avoid odd sized primitives; use int instead")
- for arg in m.args:
- if arg in discouraged:
- warn(clazz, m, "FW12", "Should avoid odd sized primitives; use int instead")
-
-
-PRIMITIVES = {"void", "int", "float", "boolean", "short", "char", "byte", "long", "double"}
-
-@verifier
-def verify_nullability(clazz):
- """Catches missing nullability annotations"""
-
- for f in clazz.fields:
- if "enum_constant" in f.split:
- continue # Enum constants are never null
- if f.value is not None and 'final' in f.split:
- continue # Nullability of constants can be inferred.
- if f.typ not in PRIMITIVES and not has_nullability(f.annotations):
- error(clazz, f, "M12", "Field must be marked either @NonNull or @Nullable")
-
- for c in clazz.ctors:
- verify_nullability_args(clazz, c)
-
- for m in clazz.methods:
- if m.name == "writeToParcel" or m.name == "onReceive" or m.name == "onBind":
- continue # Parcelable.writeToParcel(), BroadcastReceiver.onReceive(), and Service.onBind() are not yet annotated
-
- if (m.name == "equals" and m.args == ["java.lang.Object"] or
- m.name == "toString" and m.args == []):
- continue # Nullability of equals and toString is implicit.
-
- if m.typ not in PRIMITIVES and not has_nullability(m.annotations):
- error(clazz, m, "M12", "Return value must be marked either @NonNull or @Nullable")
- verify_nullability_args(clazz, m)
-
-def verify_nullability_args(clazz, m):
- for i, arg in enumerate(m.detailed_args):
- if arg.type not in PRIMITIVES and not has_nullability(arg.annotations):
- error(clazz, m, "M12", "Argument %d must be marked either @NonNull or @Nullable" % (i+1,))
-
-def has_nullability(annotations):
- return "@NonNull" in annotations or "@Nullable" in annotations
-
-
-@verifier
-def verify_intdef(clazz):
- """intdefs must be @hide, because the constant names cannot be stored in
- the stubs (only the values are, which is not useful)"""
- if "@interface" not in clazz.split:
- return
- if "@IntDef" in clazz.annotations or "@LongDef" in clazz.annotations:
- error(clazz, None, None, "@IntDef and @LongDef annotations must be @hide")
-
-
-@verifier
-def verify_singleton(clazz):
- """Catch singleton objects with constructors."""
-
- singleton = False
- for m in clazz.methods:
- if m.name.startswith("get") and m.name.endswith("Instance") and " static " in m.raw:
- singleton = True
-
- if singleton:
- for c in clazz.ctors:
- error(clazz, c, None, "Singleton classes should use getInstance() methods")
-
-
-
-def is_interesting(clazz):
- """Test if given class is interesting from an Android PoV."""
-
- if clazz.pkg.name.startswith("java"): return False
- if clazz.pkg.name.startswith("junit"): return False
- if clazz.pkg.name.startswith("org.apache"): return False
- if clazz.pkg.name.startswith("org.xml"): return False
- if clazz.pkg.name.startswith("org.json"): return False
- if clazz.pkg.name.startswith("org.w3c"): return False
- if clazz.pkg.name.startswith("android.icu."): return False
- return True
-
-
-def examine_clazz(clazz):
- """Find all style issues in the given class."""
-
- notice(clazz)
-
- if not is_interesting(clazz): return
-
- for v in verifiers.itervalues():
- v(clazz)
-
- if not ALLOW_GOOGLE: verify_google(clazz)
-
-
-def examine_stream(stream, base_stream=None, in_classes_with_base=[], out_classes_with_base=None):
- """Find all style issues in the given API stream."""
- global failures, noticed
- failures = {}
- noticed = {}
- _parse_stream(stream, examine_clazz, base_f=base_stream,
- in_classes_with_base=in_classes_with_base,
- out_classes_with_base=out_classes_with_base)
- return (failures, noticed)
-
-
-def examine_api(api):
- """Find all style issues in the given parsed API."""
- global failures
- failures = {}
- for key in sorted(api.keys()):
- examine_clazz(api[key])
- return failures
-
-
-def verify_compat(cur, prev):
- """Find any incompatible API changes between two levels."""
- global failures
-
- def class_exists(api, test):
- return test.fullname in api
-
- def ctor_exists(api, clazz, test):
- for m in clazz.ctors:
- if m.ident == test.ident: return True
- return False
-
- def all_methods(api, clazz):
- methods = list(clazz.methods)
- if clazz.extends is not None:
- methods.extend(all_methods(api, api[clazz.extends]))
- return methods
-
- def method_exists(api, clazz, test):
- methods = all_methods(api, clazz)
- for m in methods:
- if m.ident == test.ident: return True
- return False
-
- def field_exists(api, clazz, test):
- for f in clazz.fields:
- if f.ident == test.ident: return True
- return False
-
- failures = {}
- for key in sorted(prev.keys()):
- prev_clazz = prev[key]
-
- if not class_exists(cur, prev_clazz):
- error(prev_clazz, None, None, "Class removed or incompatible change")
- continue
-
- cur_clazz = cur[key]
-
- for test in prev_clazz.ctors:
- if not ctor_exists(cur, cur_clazz, test):
- error(prev_clazz, prev_ctor, None, "Constructor removed or incompatible change")
-
- methods = all_methods(prev, prev_clazz)
- for test in methods:
- if not method_exists(cur, cur_clazz, test):
- error(prev_clazz, test, None, "Method removed or incompatible change")
-
- for test in prev_clazz.fields:
- if not field_exists(cur, cur_clazz, test):
- error(prev_clazz, test, None, "Field removed or incompatible change")
-
- return failures
-
-
-def match_filter(filters, fullname):
- for f in filters:
- if fullname == f:
- return True
- if fullname.startswith(f + '.'):
- return True
- return False
-
-
-def show_deprecations_at_birth(cur, prev):
- """Show API deprecations at birth."""
- global failures
-
- # Remove all existing things so we're left with new
- for prev_clazz in prev.values():
- if prev_clazz.fullname not in cur:
- # The class was removed this release; we can safely ignore it.
- continue
-
- cur_clazz = cur[prev_clazz.fullname]
- if not is_interesting(cur_clazz): continue
-
- sigs = { i.ident: i for i in prev_clazz.ctors }
- cur_clazz.ctors = [ i for i in cur_clazz.ctors if i.ident not in sigs ]
- sigs = { i.ident: i for i in prev_clazz.methods }
- cur_clazz.methods = [ i for i in cur_clazz.methods if i.ident not in sigs ]
- sigs = { i.ident: i for i in prev_clazz.fields }
- cur_clazz.fields = [ i for i in cur_clazz.fields if i.ident not in sigs ]
-
- # Forget about class entirely when nothing new
- if len(cur_clazz.ctors) == 0 and len(cur_clazz.methods) == 0 and len(cur_clazz.fields) == 0:
- del cur[prev_clazz.fullname]
-
- for clazz in cur.values():
- if not is_interesting(clazz): continue
-
- if "deprecated" in clazz.split and not clazz.fullname in prev:
- error(clazz, None, None, "Found API deprecation at birth")
-
- for i in clazz.ctors + clazz.methods + clazz.fields:
- if "deprecated" in i.split:
- error(clazz, i, None, "Found API deprecation at birth")
-
- print "%s Deprecated at birth %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True),
- format(reset=True)))
- for f in sorted(failures):
- print failures[f]
- print
-
-
-def show_stats(cur, prev):
- """Show API stats."""
-
- stats = collections.defaultdict(int)
- for cur_clazz in cur.values():
- if not is_interesting(cur_clazz): continue
-
- if cur_clazz.fullname not in prev:
- stats['new_classes'] += 1
- stats['new_ctors'] += len(cur_clazz.ctors)
- stats['new_methods'] += len(cur_clazz.methods)
- stats['new_fields'] += len(cur_clazz.fields)
- else:
- prev_clazz = prev[cur_clazz.fullname]
-
- sigs = { i.ident: i for i in prev_clazz.ctors }
- ctors = len([ i for i in cur_clazz.ctors if i.ident not in sigs ])
- sigs = { i.ident: i for i in prev_clazz.methods }
- methods = len([ i for i in cur_clazz.methods if i.ident not in sigs ])
- sigs = { i.ident: i for i in prev_clazz.fields }
- fields = len([ i for i in cur_clazz.fields if i.ident not in sigs ])
-
- if ctors + methods + fields > 0:
- stats['extend_classes'] += 1
- stats['extend_ctors'] += ctors
- stats['extend_methods'] += methods
- stats['extend_fields'] += fields
-
- print "#", "".join([ k.ljust(20) for k in sorted(stats.keys()) ])
- print " ", "".join([ str(stats[k]).ljust(20) for k in sorted(stats.keys()) ])
-
-
-def main():
- parser = argparse.ArgumentParser(description="Enforces common Android public API design \
- patterns. It ignores lint messages from a previous API level, if provided.")
- parser.add_argument("--base-current", nargs='?', type=argparse.FileType('r'), default=None,
- help="The base current.txt to use when examining system-current.txt or"
- " test-current.txt")
- parser.add_argument("--base-previous", nargs='?', type=argparse.FileType('r'), default=None,
- help="The base previous.txt to use when examining system-previous.txt or"
- " test-previous.txt")
- parser.add_argument("--no-color", action='store_const', const=True,
- help="Disable terminal colors")
- parser.add_argument("--color", action='store_const', const=True,
- help="Use terminal colors")
- parser.add_argument("--allow-google", action='store_const', const=True,
- help="Allow references to Google")
- parser.add_argument("--show-noticed", action='store_const', const=True,
- help="Show API changes noticed")
- parser.add_argument("--show-deprecations-at-birth", action='store_const', const=True,
- help="Show API deprecations at birth")
- parser.add_argument("--show-stats", action='store_const', const=True,
- help="Show API stats")
- parser.add_argument("--title", action='store', default=None,
- help="Title to put in for display purposes")
- parser.add_argument("--filter", action="append",
- help="If provided, only show lint for the given packages or classes.")
- parser.add_argument("current.txt", type=argparse.FileType('r'), help="current.txt")
- parser.add_argument("previous.txt", nargs='?', type=argparse.FileType('r'), default=None,
- help="previous.txt")
- args = vars(parser.parse_args())
-
- if args['no_color']:
- USE_COLOR = False
- elif args['color']:
- USE_COLOR = True
- else:
- USE_COLOR = sys.stdout.isatty()
-
- if args['allow_google']:
- ALLOW_GOOGLE = True
-
- current_file = args['current.txt']
- base_current_file = args['base_current']
- previous_file = args['previous.txt']
- base_previous_file = args['base_previous']
- filters = args['filter']
- if not filters:
- filters = []
- title = args['title']
- if not title:
- title = current_file.name
-
- if args['show_deprecations_at_birth']:
- with current_file as f:
- cur = _parse_stream(f)
- with previous_file as f:
- prev = _parse_stream(f)
- show_deprecations_at_birth(cur, prev)
- sys.exit()
-
- if args['show_stats']:
- with current_file as f:
- cur = _parse_stream(f)
- with previous_file as f:
- prev = _parse_stream(f)
- show_stats(cur, prev)
- sys.exit()
-
- classes_with_base = []
-
- with current_file as f:
- if base_current_file:
- with base_current_file as base_f:
- cur_fail, cur_noticed = examine_stream(f, base_f,
- out_classes_with_base=classes_with_base)
- else:
- cur_fail, cur_noticed = examine_stream(f, out_classes_with_base=classes_with_base)
-
- if not previous_file is None:
- with previous_file as f:
- if base_previous_file:
- with base_previous_file as base_f:
- prev_fail, prev_noticed = examine_stream(f, base_f,
- in_classes_with_base=classes_with_base)
- else:
- prev_fail, prev_noticed = examine_stream(f, in_classes_with_base=classes_with_base)
-
- # ignore errors from previous API level
- for p in prev_fail:
- if p in cur_fail:
- del cur_fail[p]
-
- # ignore classes unchanged from previous API level
- for k, v in prev_noticed.iteritems():
- if k in cur_noticed and v == cur_noticed[k]:
- del cur_noticed[k]
-
- """
- # NOTE: disabled because of memory pressure
- # look for compatibility issues
- compat_fail = verify_compat(cur, prev)
-
- print "%s API compatibility issues %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), format(reset=True)))
- for f in sorted(compat_fail):
- print compat_fail[f]
- print
- """
-
- # ignore everything but the given filters, if provided
- if filters:
- cur_fail = dict([(key, failure) for key, failure in cur_fail.iteritems()
- if match_filter(filters, failure.clazz.fullname)])
-
- if args['show_noticed'] and len(cur_noticed) != 0:
- print "%s API changes noticed %s\n" % ((format(fg=WHITE, bg=BLUE, bold=True), format(reset=True)))
- for f in sorted(cur_noticed.keys()):
- print f
- print
-
- if len(cur_fail) != 0:
- print "%s API style issues: %s %s" % ((format(fg=WHITE, bg=BLUE, bold=True),
- title, format(reset=True)))
- for f in filters:
- print "%s filter: %s %s" % ((format(fg=WHITE, bg=BLUE, bold=True),
- f, format(reset=True)))
- print
- for f in sorted(cur_fail):
- print cur_fail[f]
- print
- print "%d errors" % len(cur_fail)
- sys.exit(77)
-
-if __name__ == "__main__":
- try:
- main()
- except KeyboardInterrupt:
- sys.exit(1)
diff --git a/tools/apilint/apilint_sha.sh b/tools/apilint/apilint_sha.sh
deleted file mode 100755
index 2a45b10..0000000
--- a/tools/apilint/apilint_sha.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-if git show --name-only --pretty=format: $1 | grep api/ > /dev/null; then
- python tools/apilint/apilint.py <(git show $1:api/current.txt) <(git show $1^:api/current.txt)
-fi
diff --git a/tools/apilint/apilint_sha_system.sh b/tools/apilint/apilint_sha_system.sh
deleted file mode 100755
index 8538a3d..0000000
--- a/tools/apilint/apilint_sha_system.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/bash
-
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the 'License');
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an 'AS IS' BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if git show --name-only --pretty=format: $1 | grep api/ > /dev/null; then
- python tools/apilint/apilint.py \
- --base-current <(git show $1:api/current.txt) \
- --base-previous <(git show $1^:api/current.txt) \
- <(git show $1:api/system-current.txt) \
- <(git show $1^:api/system-current.txt)
-fi
diff --git a/tools/apilint/apilint_stats.sh b/tools/apilint/apilint_stats.sh
deleted file mode 100755
index 052d9a5..0000000
--- a/tools/apilint/apilint_stats.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-API=28
-while [ $API -gt 14 ]; do
- echo "# Changes in API $((API))"
- python tools/apilint/apilint.py --show-stats ../../prebuilts/sdk/$((API))/public/api/android.txt ../../prebuilts/sdk/$((API-1))/public/api/android.txt
- let API=API-1
-done
diff --git a/tools/apilint/apilint_test.py b/tools/apilint/apilint_test.py
deleted file mode 100644
index 811cb9a..0000000
--- a/tools/apilint/apilint_test.py
+++ /dev/null
@@ -1,414 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the 'License');
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an 'AS IS' BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import unittest
-
-import apilint
-
-def cls(pkg, name):
- return apilint.Class(apilint.Package(999, "package %s {" % pkg, None), 999,
- "public final class %s {" % name, None)
-
-_ri = apilint._retry_iterator
-
-c1 = cls("android.app", "ActivityManager")
-c2 = cls("android.app", "Notification")
-c3 = cls("android.app", "Notification.Action")
-c4 = cls("android.graphics", "Bitmap")
-
-class UtilTests(unittest.TestCase):
- def test_retry_iterator(self):
- it = apilint._retry_iterator([1, 2, 3, 4])
- self.assertEqual(it.next(), 1)
- self.assertEqual(it.next(), 2)
- self.assertEqual(it.next(), 3)
- it.send("retry")
- self.assertEqual(it.next(), 3)
- self.assertEqual(it.next(), 4)
- with self.assertRaises(StopIteration):
- it.next()
-
- def test_retry_iterator_one(self):
- it = apilint._retry_iterator([1])
- self.assertEqual(it.next(), 1)
- it.send("retry")
- self.assertEqual(it.next(), 1)
- with self.assertRaises(StopIteration):
- it.next()
-
- def test_retry_iterator_one(self):
- it = apilint._retry_iterator([1])
- self.assertEqual(it.next(), 1)
- it.send("retry")
- self.assertEqual(it.next(), 1)
- with self.assertRaises(StopIteration):
- it.next()
-
- def test_skip_to_matching_class_found(self):
- it = _ri([c1, c2, c3, c4])
- self.assertEquals(apilint._skip_to_matching_class(it, c3),
- c3)
- self.assertEqual(it.next(), c4)
-
- def test_skip_to_matching_class_not_found(self):
- it = _ri([c1, c2, c3, c4])
- self.assertEquals(apilint._skip_to_matching_class(it, cls("android.content", "ContentProvider")),
- None)
- self.assertEqual(it.next(), c4)
-
- def test_yield_until_matching_class_found(self):
- it = _ri([c1, c2, c3, c4])
- self.assertEquals(list(apilint._yield_until_matching_class(it, c3)),
- [c1, c2])
- self.assertEqual(it.next(), c4)
-
- def test_yield_until_matching_class_not_found(self):
- it = _ri([c1, c2, c3, c4])
- self.assertEquals(list(apilint._yield_until_matching_class(it, cls("android.content", "ContentProvider"))),
- [c1, c2, c3])
- self.assertEqual(it.next(), c4)
-
- def test_yield_until_matching_class_None(self):
- it = _ri([c1, c2, c3, c4])
- self.assertEquals(list(apilint._yield_until_matching_class(it, None)),
- [c1, c2, c3, c4])
-
-
-faulty_current_txt = """
-// Signature format: 2.0
-package android.app {
- public final class Activity {
- }
-
- public final class WallpaperColors implements android.os.Parcelable {
- ctor public WallpaperColors(@NonNull android.os.Parcel);
- method public int describeContents();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
- }
-}
-""".strip().split('\n')
-
-ok_current_txt = """
-// Signature format: 2.0
-package android.app {
- public final class Activity {
- }
-
- public final class WallpaperColors implements android.os.Parcelable {
- ctor public WallpaperColors();
- method public int describeContents();
- method public void writeToParcel(@NonNull android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.app.WallpaperColors> CREATOR;
- }
-}
-""".strip().split('\n')
-
-system_current_txt = """
-// Signature format: 2.0
-package android.app {
- public final class WallpaperColors implements android.os.Parcelable {
- method public int getSomething();
- }
-}
-""".strip().split('\n')
-
-
-
-class BaseFileTests(unittest.TestCase):
- def test_base_file_avoids_errors(self):
- failures, _ = apilint.examine_stream(system_current_txt, ok_current_txt)
- self.assertEquals(failures, {})
-
- def test_class_with_base_finds_same_errors(self):
- failures_with_classes_with_base, _ = apilint.examine_stream("", faulty_current_txt,
- in_classes_with_base=[cls("android.app", "WallpaperColors")])
- failures_with_system_txt, _ = apilint.examine_stream(system_current_txt, faulty_current_txt)
-
- self.assertEquals(failures_with_classes_with_base.keys(), failures_with_system_txt.keys())
-
- def test_classes_with_base_is_emited(self):
- classes_with_base = []
- _, _ = apilint.examine_stream(system_current_txt, faulty_current_txt,
- out_classes_with_base=classes_with_base)
- self.assertEquals(map(lambda x: x.fullname, classes_with_base), ["android.app.WallpaperColors"])
-
-class ParseV2Stream(unittest.TestCase):
- def test_field_kinds(self):
- api = apilint._parse_stream("""
-// Signature format: 2.0
-package android {
- public enum SomeEnum {
- enum_constant public static final android.SomeEnum ENUM_CONST;
- field public static final int FIELD_CONST;
- property public final int someProperty;
- ctor public SomeEnum();
- method public Object? getObject();
- }
-}
- """.strip().split('\n'))
-
- self.assertEquals(api['android.SomeEnum'].fields[0].split[0], 'enum_constant')
- self.assertEquals(api['android.SomeEnum'].fields[1].split[0], 'field')
- self.assertEquals(api['android.SomeEnum'].fields[2].split[0], 'property')
- self.assertEquals(api['android.SomeEnum'].ctors[0].split[0], 'ctor')
- self.assertEquals(api['android.SomeEnum'].methods[0].split[0], 'method')
-
-class ParseV3Stream(unittest.TestCase):
- def test_field_kinds(self):
- api = apilint._parse_stream("""
-// Signature format: 3.0
-package a {
-
- public final class ContextKt {
- method public static inline <reified T> T! getSystemService(android.content.Context);
- method public static inline void withStyledAttributes(android.content.Context, android.util.AttributeSet? set = null, int[] attrs, @AttrRes int defStyleAttr = 0, @StyleRes int defStyleRes = 0, kotlin.jvm.functions.Function1<? super android.content.res.TypedArray,kotlin.Unit> block);
- }
-}
- """.strip().split('\n'))
- self.assertEquals(api['a.ContextKt'].methods[0].name, 'getSystemService')
- self.assertEquals(api['a.ContextKt'].methods[0].split[:4], ['method', 'public', 'static', 'inline'])
- self.assertEquals(api['a.ContextKt'].methods[1].name, 'withStyledAttributes')
- self.assertEquals(api['a.ContextKt'].methods[1].split[:4], ['method', 'public', 'static', 'inline'])
-
-class V2TokenizerTests(unittest.TestCase):
- def _test(self, raw, expected):
- self.assertEquals(apilint.V2Tokenizer(raw).tokenize(), expected)
-
- def test_simple(self):
- self._test(" method public some.Type someName(some.Argument arg, int arg);",
- ['method', 'public', 'some.Type', 'someName', '(', 'some.Argument',
- 'arg', ',', 'int', 'arg', ')', ';'])
- self._test("class Some.Class extends SomeOther {",
- ['class', 'Some.Class', 'extends', 'SomeOther', '{'])
-
- def test_varargs(self):
- self._test("name(String...)",
- ['name', '(', 'String', '...', ')'])
-
- def test_kotlin(self):
- self._test("String? name(String!...)",
- ['String', '?', 'name', '(', 'String', '!', '...', ')'])
-
- def test_annotation(self):
- self._test("method @Nullable public void name();",
- ['method', '@', 'Nullable', 'public', 'void', 'name', '(', ')', ';'])
-
- def test_annotation_args(self):
- self._test("@Some(val=1, other=2) class Class {",
- ['@', 'Some', '(', 'val', '=', '1', ',', 'other', '=', '2', ')',
- 'class', 'Class', '{'])
- def test_comment(self):
- self._test("some //comment", ['some'])
-
- def test_strings(self):
- self._test(r'"" "foo" "\"" "\\"', ['""', '"foo"', r'"\""', r'"\\"'])
-
- def test_at_interface(self):
- self._test("public @interface Annotation {",
- ['public', '@interface', 'Annotation', '{'])
-
- def test_array_type(self):
- self._test("int[][]", ['int', '[]', '[]'])
-
- def test_generics(self):
- self._test("<>foobar<A extends Object>",
- ['<', '>', 'foobar', '<', 'A', 'extends', 'Object', '>'])
-
-class V2ParserTests(unittest.TestCase):
- def _cls(self, raw):
- pkg = apilint.Package(999, "package pkg {", None)
- return apilint.Class(pkg, 1, raw, '', sig_format=2)
-
- def _method(self, raw, cls=None):
- if not cls:
- cls = self._cls("class Class {")
- return apilint.Method(cls, 1, raw, '', sig_format=2)
-
- def _field(self, raw):
- cls = self._cls("class Class {")
- return apilint.Field(cls, 1, raw, '', sig_format=2)
-
- def test_parse_package(self):
- pkg = apilint.Package(999, "package wifi.p2p {", None)
- self.assertEquals("wifi.p2p", pkg.name)
-
- def test_class(self):
- cls = self._cls("@Deprecated @IntRange(from=1, to=2) public static abstract class Some.Name extends Super<Class> implements Interface<Class> {")
- self.assertTrue('deprecated' in cls.split)
- self.assertTrue('static' in cls.split)
- self.assertTrue('abstract' in cls.split)
- self.assertTrue('class' in cls.split)
- self.assertEquals('Super', cls.extends)
- self.assertEquals('Interface', cls.implements)
- self.assertEquals('pkg.Some.Name', cls.fullname)
-
- def test_enum(self):
- cls = self._cls("public enum Some.Name {")
- self._field("enum_constant public static final android.ValueType COLOR;")
-
- def test_interface(self):
- cls = self._cls("@Deprecated @IntRange(from=1, to=2) public interface Some.Name extends Interface<Class> {")
- self.assertTrue('deprecated' in cls.split)
- self.assertTrue('interface' in cls.split)
- self.assertEquals('Interface', cls.extends)
- self.assertEquals('Interface', cls.implements)
- self.assertEquals('pkg.Some.Name', cls.fullname)
-
- def test_at_interface(self):
- cls = self._cls("@java.lang.annotation.Target({java.lang.annotation.ElementType.TYPE, java.lang.annotation.ElementType.FIELD, java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.PARAMETER, java.lang.annotation.ElementType.CONSTRUCTOR, java.lang.annotation.ElementType.LOCAL_VARIABLE}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS) public @interface SuppressLint {")
- self.assertTrue('@interface' in cls.split)
- self.assertEquals('pkg.SuppressLint', cls.fullname)
-
- def test_parse_method(self):
- m = self._method("method @Deprecated public static native <T> Class<T>[][] name("
- + "Class<T[]>[][], Class<T[][][]>[][]...) throws Exception, T;")
- self.assertTrue('static' in m.split)
- self.assertTrue('public' in m.split)
- self.assertTrue('method' in m.split)
- self.assertTrue('native' in m.split)
- self.assertTrue('deprecated' in m.split)
- self.assertEquals('java.lang.Class[][]', m.typ)
- self.assertEquals('name', m.name)
- self.assertEquals(['java.lang.Class[][]', 'java.lang.Class[][]...'], m.args)
- self.assertEquals(['java.lang.Exception', 'T'], m.throws)
-
- def test_ctor(self):
- m = self._method("ctor @Deprecated <T> ClassName();")
- self.assertTrue('ctor' in m.split)
- self.assertTrue('deprecated' in m.split)
- self.assertEquals('ctor', m.typ)
- self.assertEquals('ClassName', m.name)
-
- def test_parse_annotation_method(self):
- cls = self._cls("@interface Annotation {")
- self._method('method abstract String category() default "";', cls=cls)
- self._method('method abstract boolean deepExport() default false;', cls=cls)
- self._method('method abstract ViewDebug.FlagToString[] flagMapping() default {};', cls=cls)
- self._method('method abstract ViewDebug.FlagToString[] flagMapping() default (double)java.lang.Float.NEGATIVE_INFINITY;', cls=cls)
-
- def test_parse_string_field(self):
- f = self._field('field @Deprecated public final String SOME_NAME = "value";')
- self.assertTrue('field' in f.split)
- self.assertTrue('deprecated' in f.split)
- self.assertTrue('final' in f.split)
- self.assertEquals('java.lang.String', f.typ)
- self.assertEquals('SOME_NAME', f.name)
- self.assertEquals('value', f.value)
-
- def test_parse_field(self):
- f = self._field('field public Object SOME_NAME;')
- self.assertTrue('field' in f.split)
- self.assertEquals('java.lang.Object', f.typ)
- self.assertEquals('SOME_NAME', f.name)
- self.assertEquals(None, f.value)
-
- def test_parse_int_field(self):
- f = self._field('field public int NAME = 123;')
- self.assertTrue('field' in f.split)
- self.assertEquals('int', f.typ)
- self.assertEquals('NAME', f.name)
- self.assertEquals('123', f.value)
-
- def test_parse_quotient_field(self):
- f = self._field('field public int NAME = (0.0/0.0);')
- self.assertTrue('field' in f.split)
- self.assertEquals('int', f.typ)
- self.assertEquals('NAME', f.name)
- self.assertEquals('( 0.0 / 0.0 )', f.value)
-
- def test_kotlin_types(self):
- self._field('field public List<Integer[]?[]!>?[]![]? NAME;')
- self._method("method <T?> Class<T!>?[]![][]? name(Type!, Type argname,"
- + "Class<T?>[][]?[]!...!) throws Exception, T;")
- self._method("method <T> T name(T a = 1, T b = A(1), Lambda f = { false }, N? n = null, "
- + """double c = (1/0), float d = 1.0f, String s = "heyo", char c = 'a');""")
-
- def test_kotlin_operator(self):
- self._method('method public operator void unaryPlus(androidx.navigation.NavDestination);')
- self._method('method public static operator androidx.navigation.NavDestination get(androidx.navigation.NavGraph, @IdRes int id);')
- self._method('method public static operator <T> T get(androidx.navigation.NavigatorProvider, kotlin.reflect.KClass<T> clazz);')
-
- def test_kotlin_property(self):
- self._field('property public VM value;')
- self._field('property public final String? action;')
-
- def test_kotlin_varargs(self):
- self._method('method public void error(int p = "42", Integer int2 = "null", int p1 = "42", vararg String args);')
-
- def test_kotlin_default_values(self):
- self._method('method public void foo(String! = null, String! = "Hello World", int = 42);')
- self._method('method void method(String, String firstArg = "hello", int secondArg = "42", String thirdArg = "world");')
- self._method('method void method(String, String firstArg = "hello", int secondArg = "42");')
- self._method('method void method(String, String firstArg = "hello");')
- self._method('method void edit(android.Type, boolean commit = false, Function1<? super Editor,kotlin.Unit> action);')
- self._method('method <K, V> LruCache<K,V> lruCache(int maxSize, Function2<? super K,? super V,java.lang.Integer> sizeOf = { _, _ -> 1 }, Function1<? extends V> create = { (V)null }, Function4<kotlin.Unit> onEntryRemoved = { _, _, _, _ -> });')
- self._method('method android.Bitmap? drawToBitmap(android.View, android.Config config = android.graphics.Bitmap.Config.ARGB_8888);')
- self._method('method void emptyLambda(Function0<kotlin.Unit> sizeOf = {});')
- self._method('method void method1(int p = 42, Integer? int2 = null, int p1 = 42, String str = "hello world", java.lang.String... args);')
- self._method('method void method2(int p, int int2 = (2 * int) * some.other.pkg.Constants.Misc.SIZE);')
- self._method('method void method3(String str, int p, int int2 = double(int) + str.length);')
- self._method('method void print(test.pkg.Foo foo = test.pkg.Foo());')
-
- def test_type_use_annotation(self):
- self._method('method public static int codePointAt(char @NonNull [], int);')
- self._method('method @NonNull public java.util.Set<java.util.Map.@NonNull Entry<K,V>> entrySet();')
-
- m = self._method('method @NonNull public java.lang.annotation.@NonNull Annotation @NonNull [] getAnnotations();')
- self.assertEquals('java.lang.annotation.Annotation[]', m.typ)
-
- m = self._method('method @NonNull public abstract java.lang.annotation.@NonNull Annotation @NonNull [] @NonNull [] getParameterAnnotations();')
- self.assertEquals('java.lang.annotation.Annotation[][]', m.typ)
-
- m = self._method('method @NonNull public @NonNull String @NonNull [] split(@NonNull String, int);')
- self.assertEquals('java.lang.String[]', m.typ)
-
-class PackageTests(unittest.TestCase):
- def _package(self, raw):
- return apilint.Package(123, raw, "blame")
-
- def test_regular_package(self):
- p = self._package("package an.pref.int {")
- self.assertEquals('an.pref.int', p.name)
-
- def test_annotation_package(self):
- p = self._package("package @RestrictTo(a.b.C) an.pref.int {")
- self.assertEquals('an.pref.int', p.name)
-
- def test_multi_annotation_package(self):
- p = self._package("package @Rt(a.b.L_G_P) @RestrictTo(a.b.C) an.pref.int {")
- self.assertEquals('an.pref.int', p.name)
-
-class FilterTests(unittest.TestCase):
- def test_filter_match_prefix(self):
- self.assertTrue(apilint.match_filter(["a"], "a.B"))
- self.assertTrue(apilint.match_filter(["a.B"], "a.B.C"))
-
- def test_filter_dont_match_prefix(self):
- self.assertFalse(apilint.match_filter(["c"], "a.B"))
- self.assertFalse(apilint.match_filter(["a."], "a.B"))
- self.assertFalse(apilint.match_filter(["a.B."], "a.B.C"))
-
- def test_filter_match_exact(self):
- self.assertTrue(apilint.match_filter(["a.B"], "a.B"))
-
- def test_filter_dont_match_exact(self):
- self.assertFalse(apilint.match_filter([""], "a.B"))
- self.assertFalse(apilint.match_filter(["a.C"], "a.B"))
- self.assertFalse(apilint.match_filter(["a.C"], "a.B"))
-
-if __name__ == "__main__":
- unittest.main()
diff --git a/tools/codegen/src/com/android/codegen/ClassInfo.kt b/tools/codegen/src/com/android/codegen/ClassInfo.kt
index 92da9da..bf95a2e 100644
--- a/tools/codegen/src/com/android/codegen/ClassInfo.kt
+++ b/tools/codegen/src/com/android/codegen/ClassInfo.kt
@@ -1,47 +1,15 @@
package com.android.codegen
-import com.github.javaparser.ParseProblemException
-import com.github.javaparser.ParseResult
-import com.github.javaparser.ast.CompilationUnit
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration
-open class ClassInfo(val sourceLines: List<String>) {
+open class ClassInfo(val classAst: ClassOrInterfaceDeclaration, val fileInfo: FileInfo) {
- private val userSourceCode = (sourceLines + "}").joinToString("\n")
- val fileAst: CompilationUnit = try {
- JAVA_PARSER.parse(userSourceCode).throwIfFailed()
- } catch (e: ParseProblemException) {
- throw parseFailed(cause = e)
- }
+ val fileAst = fileInfo.fileAst
- fun <T> ParseResult<T>.throwIfFailed(): T {
- if (problems.isNotEmpty()) {
- throw parseFailed(
- desc = this@throwIfFailed.problems.joinToString("\n"),
- cause = this@throwIfFailed.problems.mapNotNull { it.cause.orElse(null) }.firstOrNull())
- }
- return result.get()
- }
-
- private fun parseFailed(cause: Throwable? = null, desc: String = ""): RuntimeException {
- return RuntimeException("Failed to parse code:\n" +
- userSourceCode
- .lines()
- .mapIndexed { lnNum, ln -> "/*$lnNum*/$ln" }
- .joinToString("\n") + "\n$desc",
- cause)
- }
-
- val classAst = fileAst.types[0] as ClassOrInterfaceDeclaration
val nestedClasses = classAst.members.filterIsInstance<ClassOrInterfaceDeclaration>()
- val superInterfaces = (fileAst.types[0] as ClassOrInterfaceDeclaration)
- .implementedTypes.map { it.asString() }
-
- val superClass = run {
- val superClasses = (fileAst.types[0] as ClassOrInterfaceDeclaration).extendedTypes
- if (superClasses.isNonEmpty) superClasses[0] else null
- }
+ val superInterfaces = classAst.implementedTypes.map { it.asString() }
+ val superClass = classAst.extendedTypes.getOrNull(0)
val ClassName = classAst.nameAsString
private val genericArgsAst = classAst.typeParameters
diff --git a/tools/codegen/src/com/android/codegen/ClassPrinter.kt b/tools/codegen/src/com/android/codegen/ClassPrinter.kt
index bd72d9e..a4fd374 100644
--- a/tools/codegen/src/com/android/codegen/ClassPrinter.kt
+++ b/tools/codegen/src/com/android/codegen/ClassPrinter.kt
@@ -11,36 +11,12 @@
* [ClassInfo] + utilities for printing out new class code with proper indentation and imports
*/
class ClassPrinter(
- source: List<String>,
- private val stringBuilder: StringBuilder,
- var cliArgs: Array<String>
-) : ClassInfo(source) {
+ classAst: ClassOrInterfaceDeclaration,
+ fileInfo: FileInfo
+) : ClassInfo(classAst, fileInfo), Printer<ClassPrinter>, ImportsProvider {
val GENERATED_MEMBER_HEADER by lazy { "@$GeneratedMember" }
- // Imports
- val NonNull by lazy { classRef("android.annotation.NonNull") }
- val NonEmpty by lazy { classRef("android.annotation.NonEmpty") }
- val Nullable by lazy { classRef("android.annotation.Nullable") }
- val TextUtils by lazy { classRef("android.text.TextUtils") }
- val LinkedHashMap by lazy { classRef("java.util.LinkedHashMap") }
- val Collections by lazy { classRef("java.util.Collections") }
- val Preconditions by lazy { classRef("com.android.internal.util.Preconditions") }
- val ArrayList by lazy { classRef("java.util.ArrayList") }
- val DataClass by lazy { classRef("com.android.internal.util.DataClass") }
- val DataClassEnum by lazy { classRef("com.android.internal.util.DataClass.Enum") }
- val ParcelWith by lazy { classRef("com.android.internal.util.DataClass.ParcelWith") }
- val PluralOf by lazy { classRef("com.android.internal.util.DataClass.PluralOf") }
- val Each by lazy { classRef("com.android.internal.util.DataClass.Each") }
- val DataClassGenerated by lazy { classRef("com.android.internal.util.DataClass.Generated") }
- val DataClassSuppressConstDefs by lazy { classRef("com.android.internal.util.DataClass.SuppressConstDefsGeneration") }
- val DataClassSuppress by lazy { classRef("com.android.internal.util.DataClass.Suppress") }
- val GeneratedMember by lazy { classRef("com.android.internal.util.DataClass.Generated.Member") }
- val Parcelling by lazy { classRef("com.android.internal.util.Parcelling") }
- val Parcelable by lazy { classRef("android.os.Parcelable") }
- val Parcel by lazy { classRef("android.os.Parcel") }
- val UnsupportedAppUsage by lazy { classRef("android.annotation.UnsupportedAppUsage") }
-
init {
val fieldsWithMissingNullablity = fields.filter { field ->
!field.isPrimitive
@@ -60,49 +36,60 @@
}
}
- /**
- * Optionally shortens a class reference if there's a corresponding import present
- */
- fun classRef(fullName: String): String {
- if (cliArgs.contains(FLAG_NO_FULL_QUALIFIERS)) {
- return fullName.split(".").dropWhile { it[0].isLowerCase() }.joinToString(".")
- }
+ val cliArgs get() = fileInfo.cliArgs
- val pkg = fullName.substringBeforeLast(".")
- val simpleName = fullName.substringAfterLast(".")
- if (fileAst.imports.any { imprt ->
- imprt.nameAsString == fullName
- || (imprt.isAsterisk && imprt.nameAsString == pkg)
- }) {
- return simpleName
- } else {
- val outerClass = pkg.substringAfterLast(".", "")
- if (outerClass.firstOrNull()?.isUpperCase() == true) {
- return classRef(pkg) + "." + simpleName
- }
+ fun print() {
+ currentIndent = fileInfo.sourceLines
+ .find { "class $ClassName" in it }!!
+ .takeWhile { it.isWhitespace() }
+ .plus(INDENT_SINGLE)
+
+ +fileInfo.generatedWarning
+
+ if (FeatureFlag.CONST_DEFS()) generateConstDefs()
+
+
+ if (FeatureFlag.CONSTRUCTOR()) {
+ generateConstructor("public")
+ } else if (FeatureFlag.BUILDER()
+ || FeatureFlag.COPY_CONSTRUCTOR()
+ || FeatureFlag.WITHERS()) {
+ generateConstructor("/* package-private */")
}
- return fullName
+ if (FeatureFlag.COPY_CONSTRUCTOR()) generateCopyConstructor()
+
+ if (FeatureFlag.GETTERS()) generateGetters()
+ if (FeatureFlag.SETTERS()) generateSetters()
+ if (FeatureFlag.TO_STRING()) generateToString()
+ if (FeatureFlag.EQUALS_HASH_CODE()) generateEqualsHashcode()
+
+ if (FeatureFlag.FOR_EACH_FIELD()) generateForEachField()
+
+ if (FeatureFlag.WITHERS()) generateWithers()
+
+ if (FeatureFlag.PARCELABLE()) generateParcelable()
+
+ if (FeatureFlag.BUILDER() && FeatureFlag.BUILD_UPON()) generateBuildUpon()
+ if (FeatureFlag.BUILDER()) generateBuilder()
+
+ if (FeatureFlag.AIDL()) fileInfo.generateAidl() //TODO guard against nested classes requesting aidl
+
+ generateMetadata(fileInfo.file)
+
+ +"""
+ //@formatter:on
+ $GENERATED_END
+
+ """
+
+ rmEmptyLine()
}
- /** @see classRef */
- inline fun <reified T : Any> classRef(): String {
- return classRef(T::class.java.name)
- }
+ override var currentIndent: String
+ get() = fileInfo.currentIndent
+ set(value) { fileInfo.currentIndent = value }
+ override val stringBuilder get() = fileInfo.stringBuilder
- /** @see classRef */
- fun memberRef(fullName: String): String {
- val className = fullName.substringBeforeLast(".")
- val methodName = fullName.substringAfterLast(".")
- return if (fileAst.imports.any {
- it.isStatic
- && (it.nameAsString == fullName
- || (it.isAsterisk && it.nameAsString == className))
- }) {
- className.substringAfterLast(".") + "." + methodName
- } else {
- classRef(className) + "." + methodName
- }
- }
val dataClassAnnotationFeatures = classAst.annotations
.find { it.nameAsString == DataClass }
@@ -143,7 +130,7 @@
|| onByDefault
FeatureFlag.CONSTRUCTOR -> !FeatureFlag.BUILDER()
FeatureFlag.PARCELABLE -> "Parcelable" in superInterfaces
- FeatureFlag.AIDL -> FeatureFlag.PARCELABLE()
+ FeatureFlag.AIDL -> fileInfo.mainClass.nameAsString == ClassName && FeatureFlag.PARCELABLE()
FeatureFlag.IMPLICIT_NONNULL -> fields.any { it.isNullable }
&& fields.none { "@$NonNull" in it.annotations }
else -> onByDefault
@@ -163,162 +150,7 @@
}
}
- var currentIndent = INDENT_SINGLE
- private set
- fun pushIndent() {
- currentIndent += INDENT_SINGLE
- }
-
- fun popIndent() {
- currentIndent = currentIndent.substring(0, currentIndent.length - INDENT_SINGLE.length)
- }
-
- fun backspace() = stringBuilder.setLength(stringBuilder.length - 1)
- val lastChar get() = stringBuilder[stringBuilder.length - 1]
-
- private fun appendRaw(s: String) {
- stringBuilder.append(s)
- }
-
- fun append(s: String) {
- if (s.isBlank() && s != "\n") {
- appendRaw(s)
- } else {
- appendRaw(s.lines().map { line ->
- if (line.startsWith(" *")) line else line.trimStart()
- }.joinToString("\n$currentIndent"))
- }
- }
-
- fun appendSameLine(s: String) {
- while (lastChar.isWhitespace() || lastChar.isNewline()) {
- backspace()
- }
- appendRaw(s)
- }
-
- fun rmEmptyLine() {
- while (lastChar.isWhitespaceNonNewline()) backspace()
- if (lastChar.isNewline()) backspace()
- }
-
- /**
- * Syntactic sugar for:
- * ```
- * +"code()";
- * ```
- * to append the given string plus a newline
- */
- operator fun String.unaryPlus() = append("$this\n")
-
- /**
- * Syntactic sugar for:
- * ```
- * !"code()";
- * ```
- * to append the given string without a newline
- */
- operator fun String.not() = append(this)
-
- /**
- * Syntactic sugar for:
- * ```
- * ... {
- * ...
- * }+";"
- * ```
- * to append a ';' on same line after a block, and a newline afterwards
- */
- operator fun Unit.plus(s: String) {
- appendSameLine(s)
- +""
- }
-
- /**
- * A multi-purpose syntactic sugar for appending the given string plus anything generated in
- * the given [block], the latter with the appropriate deeper indent,
- * and resetting the indent back to original at the end
- *
- * Usage examples:
- *
- * ```
- * "if (...)" {
- * ...
- * }
- * ```
- * to append a corresponding if block appropriate indentation
- *
- * ```
- * "void foo(...)" {
- * ...
- * }
- * ```
- * similar to the previous one, plus an extra empty line after the function body
- *
- * ```
- * "void foo(" {
- * <args code>
- * }
- * ```
- * to use proper indentation for args code and close the bracket on same line at end
- *
- * ```
- * "..." {
- * ...
- * }
- * to use the correct indentation for inner code, resetting it at the end
- */
- inline operator fun String.invoke(block: ClassPrinter.() -> Unit) {
- if (this == " {") {
- appendSameLine(this)
- } else {
- append(this)
- }
- when {
- endsWith("(") -> {
- indentedBy(2, block)
- appendSameLine(")")
- }
- endsWith("{") || endsWith(")") -> {
- if (!endsWith("{")) appendSameLine(" {")
- indentedBy(1, block)
- +"}"
- if ((endsWith(") {") || endsWith(")") || this == " {")
- && !startsWith("synchronized")
- && !startsWith("switch")
- && !startsWith("if ")
- && !contains(" else ")
- && !contains("new ")
- && !contains("return ")) {
- +"" // extra line after function definitions
- }
- }
- else -> indentedBy(2, block)
- }
- }
-
- inline fun indentedBy(level: Int, block: ClassPrinter.() -> Unit) {
- append("\n")
- level times {
- append(INDENT_SINGLE)
- pushIndent()
- }
- block()
- level times { popIndent() }
- rmEmptyLine()
- +""
- }
-
- inline fun Iterable<FieldInfo>.forEachTrimmingTrailingComma(b: FieldInfo.() -> Unit) {
- forEachApply {
- b()
- if (isLast) {
- while (lastChar == ' ' || lastChar == '\n') backspace()
- if (lastChar == ',') backspace()
- }
- }
- }
inline operator fun <R> invoke(f: ClassPrinter.() -> R): R = run(f)
@@ -381,10 +213,10 @@
BuilderClass = (builderFactoryOverride.type as ClassOrInterfaceType).nameAsString
BuilderType = builderFactoryOverride.type.asString()
} else {
- val builderExtension = (fileAst.types
- + classAst.childNodes.filterIsInstance(TypeDeclaration::class.java)).find {
- it.nameAsString == CANONICAL_BUILDER_CLASS
- }
+ val builderExtension = classAst
+ .childNodes
+ .filterIsInstance(TypeDeclaration::class.java)
+ .find { it.nameAsString == CANONICAL_BUILDER_CLASS }
if (builderExtension != null) {
BuilderClass = BASE_BUILDER_CLASS
val tp = (builderExtension as ClassOrInterfaceDeclaration).typeParameters
diff --git a/tools/codegen/src/com/android/codegen/FieldInfo.kt b/tools/codegen/src/com/android/codegen/FieldInfo.kt
index 1a7fd6e..ebfbbd8 100644
--- a/tools/codegen/src/com/android/codegen/FieldInfo.kt
+++ b/tools/codegen/src/com/android/codegen/FieldInfo.kt
@@ -1,5 +1,6 @@
package com.android.codegen
+import com.github.javaparser.JavaParser
import com.github.javaparser.ast.body.FieldDeclaration
import com.github.javaparser.ast.expr.ClassExpr
import com.github.javaparser.ast.expr.Name
@@ -92,6 +93,8 @@
// Generic args
val isArray = Type.endsWith("[]")
val isList = FieldClass == "List" || FieldClass == "ArrayList"
+ val isMap = FieldClass == "Map" || FieldClass == "ArrayMap"
+ || FieldClass == "HashMap" || FieldClass == "LinkedHashMap"
val fieldBit = bitAtExpr(index)
var isLast = false
val isFinal = fieldAst.isFinal
@@ -111,11 +114,12 @@
val annotations by lazy {
if (FieldClass in BUILTIN_SPECIAL_PARCELLINGS) {
classPrinter {
- fieldAst.addAnnotation(SingleMemberAnnotationExpr(
- Name(ParcelWith),
- ClassExpr(JAVA_PARSER
- .parseClassOrInterfaceType("$Parcelling.BuiltIn.For$FieldClass")
- .throwIfFailed())))
+ fileInfo.apply {
+ fieldAst.addAnnotation(SingleMemberAnnotationExpr(
+ Name(ParcelWith),
+ ClassExpr(parseJava(JavaParser::parseClassOrInterfaceType,
+ "$Parcelling.BuiltIn.For$FieldClass"))))
+ }
}
}
fieldAst.annotations.map { it.removeComment().toString() }
@@ -195,7 +199,7 @@
listOf("String", "CharSequence", "Exception", "Size", "SizeF", "Bundle",
"FileDescriptor", "SparseBooleanArray", "SparseIntArray", "SparseArray") ->
FieldClass
- FieldClass == "Map" && fieldTypeGenegicArgs[0] == "String" -> "Map"
+ isMap && fieldTypeGenegicArgs[0] == "String" -> "Map"
isArray -> when {
FieldInnerType!! in (PRIMITIVE_TYPES + "String") -> FieldInnerType + "Array"
isBinder(FieldInnerType) -> "BinderArray"
diff --git a/tools/codegen/src/com/android/codegen/FileInfo.kt b/tools/codegen/src/com/android/codegen/FileInfo.kt
new file mode 100644
index 0000000..9094726
--- /dev/null
+++ b/tools/codegen/src/com/android/codegen/FileInfo.kt
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.codegen
+
+import com.github.javaparser.JavaParser
+import com.github.javaparser.ast.CompilationUnit
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration
+import com.github.javaparser.ast.body.TypeDeclaration
+import java.io.File
+
+/**
+ * File-level parsing & printing logic
+ *
+ * @see [main] entrypoint
+ */
+class FileInfo(
+ val sourceLines: List<String>,
+ val cliArgs: Array<String>,
+ val file: File)
+ : Printer<FileInfo>, ImportsProvider {
+
+ override val fileAst: CompilationUnit
+ = parseJava(JavaParser::parse, sourceLines.joinToString("\n"))
+
+ override val stringBuilder = StringBuilder()
+ override var currentIndent = INDENT_SINGLE
+
+
+ val generatedWarning = run {
+ val fileEscaped = file.absolutePath.replace(
+ System.getenv("ANDROID_BUILD_TOP"), "\$ANDROID_BUILD_TOP")
+
+ """
+
+
+ // $GENERATED_WARNING_PREFIX v$CODEGEN_VERSION.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ $THIS_SCRIPT_LOCATION$CODEGEN_NAME ${cliArgs.dropLast(1).joinToString("") { "$it " }}$fileEscaped
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+ """
+ }
+ private val generatedWarningNumPrecedingEmptyLines
+ = generatedWarning.lines().takeWhile { it.isBlank() }.size
+
+ val classes = fileAst.types
+ .filterIsInstance<ClassOrInterfaceDeclaration>()
+ .flatMap { it.plusNested() }
+ .filterNot { it.isInterface }
+
+ val mainClass = classes.find { it.nameAsString == file.nameWithoutExtension }!!
+
+ // Parse stage 1
+ val classBounds: List<ClassBounds> = classes.map { ast ->
+ ClassBounds(ast, fileInfo = this)
+ }.apply {
+ forEachApply {
+ if (ast.isNestedType) {
+ val parent = find {
+ it.name == (ast.parentNode.get()!! as TypeDeclaration<*>).nameAsString
+ }!!
+ parent.nested.add(this)
+ nestedIn = parent
+ }
+ }
+ }
+
+ // Parse Stage 2
+ var codeChunks = buildList<CodeChunk> {
+ val mainClassBounds = classBounds.find { it.nestedIn == null }!!
+ add(CodeChunk.FileHeader(
+ mainClassBounds.fileInfo.sourceLines.subList(0, mainClassBounds.range.start)))
+ add(CodeChunk.DataClass.parse(mainClassBounds))
+ }
+
+ // Output stage
+ fun main() {
+ codeChunks.forEach { print(it) }
+ }
+
+ fun print(chunk: CodeChunk) {
+ when(chunk) {
+ is CodeChunk.GeneratedCode -> {
+ // Re-parse class code, discarding generated code and nested dataclasses
+ val ast = chunk.owner.chunks
+ .filter {
+ it.javaClass == CodeChunk.Code::class.java
+ || it.javaClass == CodeChunk.ClosingBrace::class.java
+ }
+ .flatMap { (it as CodeChunk.Code).lines }
+ .joinToString("\n")
+ .let {
+ parseJava(JavaParser::parseTypeDeclaration, it)
+ as ClassOrInterfaceDeclaration
+ }
+
+ // Write new generated code
+ ClassPrinter(ast, fileInfo = this).print()
+ }
+ is CodeChunk.ClosingBrace -> {
+ // Special case - print closing brace with -1 indent
+ rmEmptyLine()
+ popIndent()
+ +"\n}"
+ }
+ // Print general code as-is
+ is CodeChunk.Code -> chunk.lines.forEach { stringBuilder.appendln(it) }
+ // Recursively render data classes
+ is CodeChunk.DataClass -> chunk.chunks.forEach { print(it) }
+ }
+ }
+
+ /**
+ * Output of stage 1 of parsing a file:
+ * Recursively nested ranges of code line numbers containing nested classes
+ */
+ data class ClassBounds(
+ val ast: ClassOrInterfaceDeclaration,
+ val fileInfo: FileInfo,
+ val name: String = ast.nameAsString,
+ val range: ClosedRange<Int> = ast.range.get()!!.let { rng -> rng.begin.line-1..rng.end.line-1 },
+ val nested: MutableList<ClassBounds> = mutableListOf(),
+ var nestedIn: ClassBounds? = null) {
+
+ val nestedDataClasses: List<ClassBounds> by lazy {
+ nested.filter { it.isDataclass }.sortedBy { it.range.start }
+ }
+ val isDataclass = ast.annotations.any { it.nameAsString.endsWith("DataClass") }
+
+ val baseIndentLength = fileInfo.sourceLines.find { "class $name" in it }!!.takeWhile { it == ' ' }.length
+ val baseIndent = buildString { repeat(baseIndentLength) { append(' ') } }
+
+ val sourceNoPrefix = fileInfo.sourceLines.drop(range.start)
+ val generatedCodeRange = sourceNoPrefix
+ .indexOfFirst { it.startsWith("$baseIndent$INDENT_SINGLE// $GENERATED_WARNING_PREFIX") }
+ .let { start ->
+ if (start < 0) {
+ null
+ } else {
+ var endInclusive = sourceNoPrefix.indexOfFirst {
+ it.startsWith("$baseIndent$INDENT_SINGLE$GENERATED_END")
+ }
+ if (endInclusive == -1) {
+ // Legacy generated code doesn't have end markers
+ endInclusive = sourceNoPrefix.size - 2
+ }
+ IntRange(
+ range.start + start - fileInfo.generatedWarningNumPrecedingEmptyLines,
+ range.start + endInclusive)
+ }
+ }
+
+ /** Debug info */
+ override fun toString(): String {
+ return buildString {
+ appendln("class $name $range")
+ nested.forEach {
+ appendln(it)
+ }
+ appendln("end $name")
+ }
+ }
+ }
+
+ /**
+ * Output of stage 2 of parsing a file
+ */
+ sealed class CodeChunk {
+ /** General code */
+ open class Code(val lines: List<String>): CodeChunk() {}
+
+ /** Copyright + package + imports + main javadoc */
+ class FileHeader(lines: List<String>): Code(lines)
+
+ /** Code to be discarded and refreshed */
+ open class GeneratedCode(lines: List<String>): Code(lines) {
+ lateinit var owner: DataClass
+
+ class Placeholder: GeneratedCode(emptyList())
+ }
+
+ object ClosingBrace: Code(listOf("}"))
+
+ data class DataClass(
+ val ast: ClassOrInterfaceDeclaration,
+ val chunks: List<CodeChunk>,
+ val generatedCode: GeneratedCode?): CodeChunk() {
+
+ companion object {
+ fun parse(classBounds: ClassBounds): DataClass {
+ val initial = Code(lines = classBounds.fileInfo.sourceLines.subList(
+ fromIndex = classBounds.range.start,
+ toIndex = findLowerBound(
+ thisClass = classBounds,
+ nextNestedClass = classBounds.nestedDataClasses.getOrNull(0))))
+
+ val chunks = mutableListOf<CodeChunk>(initial)
+
+ classBounds.nestedDataClasses.forEachSequentialPair {
+ nestedDataClass, nextNestedDataClass ->
+ chunks += DataClass.parse(nestedDataClass)
+ chunks += Code(lines = classBounds.fileInfo.sourceLines.subList(
+ fromIndex = nestedDataClass.range.endInclusive + 1,
+ toIndex = findLowerBound(
+ thisClass = classBounds,
+ nextNestedClass = nextNestedDataClass)))
+ }
+
+ var generatedCode = classBounds.generatedCodeRange?.let { rng ->
+ GeneratedCode(classBounds.fileInfo.sourceLines.subList(
+ rng.start, rng.endInclusive+1))
+ }
+ if (generatedCode != null) {
+ chunks += generatedCode
+ chunks += ClosingBrace
+ } else if (classBounds.isDataclass) {
+
+ // Insert placeholder for generated code to be inserted for the 1st time
+ chunks.last = (chunks.last as Code)
+ .lines
+ .dropLastWhile { it.isBlank() }
+ .run {
+ if (last().dropWhile { it.isWhitespace() }.startsWith("}")) {
+ dropLast(1)
+ } else {
+ this
+ }
+ }.let { Code(it) }
+ generatedCode = GeneratedCode.Placeholder()
+ chunks += generatedCode
+ chunks += ClosingBrace
+ } else {
+ // Outer class may be not a @DataClass but contain ones
+ // so just skip generated code for them
+ }
+
+ return DataClass(classBounds.ast, chunks, generatedCode).also {
+ generatedCode?.owner = it
+ }
+ }
+
+ private fun findLowerBound(thisClass: ClassBounds, nextNestedClass: ClassBounds?): Int {
+ return nextNestedClass?.range?.start
+ ?: thisClass.generatedCodeRange?.start
+ ?: thisClass.range.endInclusive + 1
+ }
+ }
+ }
+
+ /** Debug info */
+ fun summary(): String = when(this) {
+ is Code -> "${javaClass.simpleName}(${lines.size} lines): ${lines.getOrNull(0)?.take(70) ?: ""}..."
+ is DataClass -> "DataClass ${ast.nameAsString}:\n" +
+ chunks.joinToString("\n") { it.summary() } +
+ "\n//end ${ast.nameAsString}"
+ }
+ }
+
+ private fun ClassOrInterfaceDeclaration.plusNested(): List<ClassOrInterfaceDeclaration> {
+ return mutableListOf<ClassOrInterfaceDeclaration>().apply {
+ add(this@plusNested)
+ childNodes.filterIsInstance<ClassOrInterfaceDeclaration>()
+ .flatMap { it.plusNested() }
+ .let { addAll(it) }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/codegen/src/com/android/codegen/Generators.kt b/tools/codegen/src/com/android/codegen/Generators.kt
index bd32f9c..dc1f4c5 100644
--- a/tools/codegen/src/com/android/codegen/Generators.kt
+++ b/tools/codegen/src/com/android/codegen/Generators.kt
@@ -119,14 +119,14 @@
}
}
-fun ClassPrinter.generateAidl(javaFile: File) {
- val aidl = File(javaFile.path.substringBeforeLast(".java") + ".aidl")
+fun FileInfo.generateAidl() {
+ val aidl = File(file.path.substringBeforeLast(".java") + ".aidl")
if (aidl.exists()) return
aidl.writeText(buildString {
sourceLines.dropLastWhile { !it.startsWith("package ") }.forEach {
appendln(it)
}
- append("\nparcelable $ClassName;\n")
+ append("\nparcelable ${mainClass.nameAsString};\n")
})
}
@@ -343,7 +343,7 @@
}
}
- if (FieldClass.endsWith("Map") && FieldInnerType != null) {
+ if (isMap && FieldInnerType != null) {
generateBuilderMethod(
name = adderName,
defVisibility = visibility,
@@ -351,7 +351,7 @@
paramNames = listOf("key", "value"),
genJavadoc = { +javadocSeeSetter }) {
!singularNameCustomizationHint
- +"if ($name == null) $setterName(new $LinkedHashMap());"
+ +"if ($name == null) $setterName(new ${if (FieldClass == "Map") LinkedHashMap else FieldClass}());"
+"$name.put(key, value);"
+"return$maybeCast this;"
}
@@ -507,7 +507,8 @@
// Create container if any
val containerInitExpr = when {
- FieldClass.endsWith("Map") -> "new $LinkedHashMap<>()"
+ FieldClass == "Map" -> "new $LinkedHashMap<>()"
+ isMap -> "new $FieldClass()"
FieldClass == "List" || FieldClass == "ArrayList" ->
"new ${classRef("java.util.ArrayList")}<>()"
else -> ""
diff --git a/tools/codegen/src/com/android/codegen/ImportsProvider.kt b/tools/codegen/src/com/android/codegen/ImportsProvider.kt
new file mode 100644
index 0000000..ba0a031
--- /dev/null
+++ b/tools/codegen/src/com/android/codegen/ImportsProvider.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.codegen
+
+import com.github.javaparser.ast.CompilationUnit
+
+/**
+ * Mixin for optionally shortening references based on existing imports
+ */
+interface ImportsProvider {
+
+ abstract val fileAst: CompilationUnit
+
+ val NonNull: String get() { return classRef("android.annotation.NonNull") }
+ val NonEmpty: String get() { return classRef("android.annotation.NonEmpty") }
+ val Nullable: String get() { return classRef("android.annotation.Nullable") }
+ val TextUtils: String get() { return classRef("android.text.TextUtils") }
+ val LinkedHashMap: String get() { return classRef("java.util.LinkedHashMap") }
+ val Collections: String get() { return classRef("java.util.Collections") }
+ val Preconditions: String get() { return classRef("com.android.internal.util.Preconditions") }
+ val ArrayList: String get() { return classRef("java.util.ArrayList") }
+ val DataClass: String get() { return classRef("com.android.internal.util.DataClass") }
+ val DataClassEnum: String get() { return classRef("com.android.internal.util.DataClass.Enum") }
+ val ParcelWith: String get() { return classRef("com.android.internal.util.DataClass.ParcelWith") }
+ val PluralOf: String get() { return classRef("com.android.internal.util.DataClass.PluralOf") }
+ val Each: String get() { return classRef("com.android.internal.util.DataClass.Each") }
+ val DataClassGenerated: String get() { return classRef("com.android.internal.util.DataClass.Generated") }
+ val DataClassSuppressConstDefs: String get() { return classRef("com.android.internal.util.DataClass.SuppressConstDefsGeneration") }
+ val DataClassSuppress: String get() { return classRef("com.android.internal.util.DataClass.Suppress") }
+ val GeneratedMember: String get() { return classRef("com.android.internal.util.DataClass.Generated.Member") }
+ val Parcelling: String get() { return classRef("com.android.internal.util.Parcelling") }
+ val Parcelable: String get() { return classRef("android.os.Parcelable") }
+ val Parcel: String get() { return classRef("android.os.Parcel") }
+ val UnsupportedAppUsage: String get() { return classRef("android.annotation.UnsupportedAppUsage") }
+
+ /**
+ * Optionally shortens a class reference if there's a corresponding import present
+ */
+ fun classRef(fullName: String): String {
+
+ val pkg = fullName.substringBeforeLast(".")
+ val simpleName = fullName.substringAfterLast(".")
+ if (fileAst.imports.any { imprt ->
+ imprt.nameAsString == fullName
+ || (imprt.isAsterisk && imprt.nameAsString == pkg)
+ }) {
+ return simpleName
+ } else {
+ val outerClass = pkg.substringAfterLast(".", "")
+ if (outerClass.firstOrNull()?.isUpperCase() == true) {
+ return classRef(pkg) + "." + simpleName
+ }
+ }
+ return fullName
+ }
+
+ /** @see classRef */
+ fun memberRef(fullName: String): String {
+ val className = fullName.substringBeforeLast(".")
+ val methodName = fullName.substringAfterLast(".")
+ return if (fileAst.imports.any {
+ it.isStatic
+ && (it.nameAsString == fullName
+ || (it.isAsterisk && it.nameAsString == className))
+ }) {
+ className.substringAfterLast(".") + "." + methodName
+ } else {
+ classRef(className) + "." + methodName
+ }
+ }
+}
+
+/** @see classRef */
+inline fun <reified T : Any> ImportsProvider.classRef(): String {
+ return classRef(T::class.java.name)
+}
\ No newline at end of file
diff --git a/tools/codegen/src/com/android/codegen/Main.kt b/tools/codegen/src/com/android/codegen/Main.kt
index ce83d3d..4b508d0 100755
--- a/tools/codegen/src/com/android/codegen/Main.kt
+++ b/tools/codegen/src/com/android/codegen/Main.kt
@@ -6,6 +6,7 @@
const val THIS_SCRIPT_LOCATION = ""
const val GENERATED_WARNING_PREFIX = "Code below generated by $CODEGEN_NAME"
+const val GENERATED_END = "// End of generated code"
const val INDENT_SINGLE = " "
val PRIMITIVE_TYPES = listOf("byte", "short", "int", "long", "char", "float", "double", "boolean")
@@ -115,81 +116,15 @@
System.exit(0)
}
val file = File(args.last()).absoluteFile
- val sourceLinesNoClosingBrace = file.readLines().dropLastWhile {
+ val sourceLisnesOriginal = file.readLines()
+ val sourceLinesNoClosingBrace = sourceLisnesOriginal.dropLastWhile {
it.startsWith("}") || it.all(Char::isWhitespace)
}
val cliArgs = handleUpdateFlag(args, sourceLinesNoClosingBrace)
- val sourceLinesAsIs = discardGeneratedCode(sourceLinesNoClosingBrace)
- val sourceLines = sourceLinesAsIs
- .filterNot { it.trim().startsWith("//") }
- .map { it.trimEnd().dropWhile { it == '\n' } }
- val stringBuilder = StringBuilder(sourceLinesAsIs.joinToString("\n"))
- ClassPrinter(sourceLines, stringBuilder, cliArgs).run {
-
- val cliExecutable = "$THIS_SCRIPT_LOCATION$CODEGEN_NAME"
- val fileEscaped = file.absolutePath.replace(
- System.getenv("ANDROID_BUILD_TOP"), "\$ANDROID_BUILD_TOP")
-
-
- +"""
-
-
-
- // $GENERATED_WARNING_PREFIX v$CODEGEN_VERSION.
- //
- // DO NOT MODIFY!
- // CHECKSTYLE:OFF Generated code
- //
- // To regenerate run:
- // $ $cliExecutable ${cliArgs.dropLast(1).joinToString("") { "$it " }}$fileEscaped
- //
- // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
- // Settings > Editor > Code Style > Formatter Control
- //@formatter:off
-
- """
-
- if (FeatureFlag.CONST_DEFS()) generateConstDefs()
-
-
- if (FeatureFlag.CONSTRUCTOR()) {
- generateConstructor("public")
- } else if (FeatureFlag.BUILDER()
- || FeatureFlag.COPY_CONSTRUCTOR()
- || FeatureFlag.WITHERS()) {
- generateConstructor("/* package-private */")
- }
- if (FeatureFlag.COPY_CONSTRUCTOR()) generateCopyConstructor()
-
- if (FeatureFlag.GETTERS()) generateGetters()
- if (FeatureFlag.SETTERS()) generateSetters()
- if (FeatureFlag.TO_STRING()) generateToString()
- if (FeatureFlag.EQUALS_HASH_CODE()) generateEqualsHashcode()
-
- if (FeatureFlag.FOR_EACH_FIELD()) generateForEachField()
-
- if (FeatureFlag.WITHERS()) generateWithers()
-
- if (FeatureFlag.PARCELABLE()) generateParcelable()
-
- if (FeatureFlag.BUILDER() && FeatureFlag.BUILD_UPON()) generateBuildUpon()
- if (FeatureFlag.BUILDER()) generateBuilder()
-
- if (FeatureFlag.AIDL()) generateAidl(file)
-
- generateMetadata(file)
-
- rmEmptyLine()
- }
- stringBuilder.append("\n}\n")
- file.writeText(stringBuilder.toString().mapLines { trimEnd() })
-}
-
-internal fun discardGeneratedCode(sourceLinesNoClosingBrace: List<String>): List<String> {
- return sourceLinesNoClosingBrace
- .takeWhile { GENERATED_WARNING_PREFIX !in it }
- .dropLastWhile(String::isBlank)
+ val fileInfo = FileInfo(sourceLisnesOriginal, cliArgs, file)
+ fileInfo.main()
+ file.writeText(fileInfo.stringBuilder.toString().mapLines { trimEnd() })
}
private fun handleUpdateFlag(cliArgs: Array<String>, sourceLines: List<String>): Array<String> {
diff --git a/tools/codegen/src/com/android/codegen/Printer.kt b/tools/codegen/src/com/android/codegen/Printer.kt
new file mode 100644
index 0000000..b30e3f6
--- /dev/null
+++ b/tools/codegen/src/com/android/codegen/Printer.kt
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.codegen
+
+/**
+ * Mixin for syntactic sugar around indent-aware printing into [stringBuilder]
+ */
+interface Printer<SELF: Printer<SELF>> {
+
+ val stringBuilder: StringBuilder
+
+ var currentIndent: String
+
+ fun pushIndent() {
+ currentIndent += INDENT_SINGLE
+ }
+
+ fun popIndent() {
+ currentIndent = if (currentIndent.length >= INDENT_SINGLE.length) {
+ currentIndent.substring(0, currentIndent.length - INDENT_SINGLE.length)
+ } else {
+ ""
+ }
+ }
+
+ fun backspace() = stringBuilder.setLength(stringBuilder.length - 1)
+ val lastChar get() = stringBuilder[stringBuilder.length - 1]
+
+ private fun appendRaw(s: String) {
+ stringBuilder.append(s)
+ }
+
+ fun append(s: String) {
+ if (s.isBlank() && s != "\n") {
+ appendRaw(s)
+ } else {
+ appendRaw(s.lines().map { line ->
+ if (line.startsWith(" *")) line else line.trimStart()
+ }.joinToString("\n$currentIndent"))
+ }
+ }
+
+ fun appendSameLine(s: String) {
+ while (lastChar.isWhitespace() || lastChar.isNewline()) {
+ backspace()
+ }
+ appendRaw(s)
+ }
+
+ fun rmEmptyLine() {
+ while (lastChar.isWhitespaceNonNewline()) backspace()
+ if (lastChar.isNewline()) backspace()
+ }
+
+ /**
+ * Syntactic sugar for:
+ * ```
+ * +"code()";
+ * ```
+ * to append the given string plus a newline
+ */
+ operator fun String.unaryPlus() = append("$this\n")
+
+ /**
+ * Syntactic sugar for:
+ * ```
+ * !"code()";
+ * ```
+ * to append the given string without a newline
+ */
+ operator fun String.not() = append(this)
+
+ /**
+ * Syntactic sugar for:
+ * ```
+ * ... {
+ * ...
+ * }+";"
+ * ```
+ * to append a ';' on same line after a block, and a newline afterwards
+ */
+ operator fun Unit.plus(s: String) {
+ appendSameLine(s)
+ +""
+ }
+
+ /**
+ * A multi-purpose syntactic sugar for appending the given string plus anything generated in
+ * the given [block], the latter with the appropriate deeper indent,
+ * and resetting the indent back to original at the end
+ *
+ * Usage examples:
+ *
+ * ```
+ * "if (...)" {
+ * ...
+ * }
+ * ```
+ * to append a corresponding if block appropriate indentation
+ *
+ * ```
+ * "void foo(...)" {
+ * ...
+ * }
+ * ```
+ * similar to the previous one, plus an extra empty line after the function body
+ *
+ * ```
+ * "void foo(" {
+ * <args code>
+ * }
+ * ```
+ * to use proper indentation for args code and close the bracket on same line at end
+ *
+ * ```
+ * "..." {
+ * ...
+ * }
+ * to use the correct indentation for inner code, resetting it at the end
+ */
+ operator fun String.invoke(block: SELF.() -> Unit) {
+ if (this == " {") {
+ appendSameLine(this)
+ } else {
+ append(this)
+ }
+ when {
+ endsWith("(") -> {
+ indentedBy(2, block)
+ appendSameLine(")")
+ }
+ endsWith("{") || endsWith(")") -> {
+ if (!endsWith("{")) appendSameLine(" {")
+ indentedBy(1, block)
+ +"}"
+ if ((endsWith(") {") || endsWith(")") || this == " {")
+ && !startsWith("synchronized")
+ && !startsWith("switch")
+ && !startsWith("if ")
+ && !contains(" else ")
+ && !contains("new ")
+ && !contains("return ")) {
+ +"" // extra line after function definitions
+ }
+ }
+ else -> indentedBy(2, block)
+ }
+ }
+
+ fun indentedBy(level: Int, block: SELF.() -> Unit) {
+ append("\n")
+ level times {
+ append(INDENT_SINGLE)
+ pushIndent()
+ }
+ (this as SELF).block()
+ level times { popIndent() }
+ rmEmptyLine()
+ +""
+ }
+
+ fun Iterable<FieldInfo>.forEachTrimmingTrailingComma(b: FieldInfo.() -> Unit) {
+ forEachApply {
+ b()
+ if (isLast) {
+ while (lastChar == ' ' || lastChar == '\n') backspace()
+ if (lastChar == ',') backspace()
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tools/codegen/src/com/android/codegen/SharedConstants.kt b/tools/codegen/src/com/android/codegen/SharedConstants.kt
index 270d34a..85c832f 100644
--- a/tools/codegen/src/com/android/codegen/SharedConstants.kt
+++ b/tools/codegen/src/com/android/codegen/SharedConstants.kt
@@ -1,7 +1,7 @@
package com.android.codegen
const val CODEGEN_NAME = "codegen"
-const val CODEGEN_VERSION = "1.0.11"
+const val CODEGEN_VERSION = "1.0.13"
const val CANONICAL_BUILDER_CLASS = "Builder"
const val BASE_BUILDER_CLASS = "BaseBuilder"
diff --git a/tools/codegen/src/com/android/codegen/Utils.kt b/tools/codegen/src/com/android/codegen/Utils.kt
index e703397..c19ae3b 100644
--- a/tools/codegen/src/com/android/codegen/Utils.kt
+++ b/tools/codegen/src/com/android/codegen/Utils.kt
@@ -1,5 +1,11 @@
package com.android.codegen
+import com.github.javaparser.JavaParser
+import com.github.javaparser.ParseProblemException
+import com.github.javaparser.ParseResult
+import com.github.javaparser.ast.Node
+import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration
+import com.github.javaparser.ast.body.TypeDeclaration
import com.github.javaparser.ast.expr.*
import com.github.javaparser.ast.nodeTypes.NodeWithModifiers
import java.time.Instant
@@ -92,3 +98,49 @@
is NormalAnnotationExpr -> pairs.map { it.name.asString() to it.value }.toMap()
else -> throw IllegalArgumentException("Unknown annotation expression: $this")
}
+
+val TypeDeclaration<*>.nestedTypes get() = childNodes.filterIsInstance<TypeDeclaration<*>>()
+val TypeDeclaration<*>.nestedDataClasses get()
+ = nestedTypes.filterIsInstance<ClassOrInterfaceDeclaration>()
+ .filter { it.annotations.any { it.nameAsString.endsWith("DataClass") } }
+val TypeDeclaration<*>.startLine get() = range.get()!!.begin.line
+
+inline fun <T> List<T>.forEachSequentialPair(action: (T, T?) -> Unit) {
+ forEachIndexed { index, t ->
+ action(t, getOrNull(index + 1))
+ }
+}
+
+fun <T: Node> parseJava(fn: JavaParser.(String) -> ParseResult<T>, source: String): T = try {
+ val parse = JAVA_PARSER.fn(source)
+ if (parse.problems.isNotEmpty()) {
+ throw parseFailed(
+ source,
+ desc = parse.problems.joinToString("\n"),
+ cause = parse.problems.mapNotNull { it.cause.orElse(null) }.firstOrNull())
+ }
+ parse.result.get()
+} catch (e: ParseProblemException) {
+ throw parseFailed(source, cause = e)
+}
+
+private fun parseFailed(source: String, cause: Throwable? = null, desc: String = ""): RuntimeException {
+ return RuntimeException("Failed to parse code:\n" +
+ source
+ .lines()
+ .mapIndexed { lnNum, ln -> "/*$lnNum*/$ln" }
+ .joinToString("\n") + "\n$desc",
+ cause)
+}
+
+var <T> MutableList<T>.last
+ get() = last()
+ set(value) {
+ if (isEmpty()) {
+ add(value)
+ } else {
+ this[size - 1] = value
+ }
+ }
+
+inline fun <T> buildList(init: MutableList<T>.() -> Unit) = mutableListOf<T>().apply(init)
\ No newline at end of file
diff --git a/tools/incident_section_gen/main.cpp b/tools/incident_section_gen/main.cpp
index 91f875e..ded4b91 100644
--- a/tools/incident_section_gen/main.cpp
+++ b/tools/incident_section_gen/main.cpp
@@ -436,7 +436,9 @@
printf(" NULL),\n");
break;
case SECTION_LOG:
- printf(" new LogSection(%d, %s),\n", field->number(), s.args().c_str());
+ printf(" new LogSection(%d, ", field->number());
+ splitAndPrint(s.args());
+ printf(" NULL),\n");
break;
case SECTION_GZIP:
printf(" new GZipSection(%d,", field->number());
diff --git a/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt b/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt
index 7fe21c7..51faa49 100644
--- a/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt
+++ b/tools/processors/staledataclass/src/android/processor/staledataclass/StaleDataclassProcessor.kt
@@ -208,7 +208,16 @@
val refreshCmd = if (file != null) {
"$CODEGEN_NAME $file"
} else {
- "find \$ANDROID_BUILD_TOP -path */${clazz.replace('.', '/')}.java -exec $CODEGEN_NAME {} \\;"
+ var gotTopLevelCalssName = false
+ val filePath = clazz.split(".")
+ .takeWhile { word ->
+ if (!gotTopLevelCalssName && word[0].isUpperCase()) {
+ gotTopLevelCalssName = true
+ return@takeWhile true
+ }
+ !gotTopLevelCalssName
+ }.joinToString("/")
+ "find \$ANDROID_BUILD_TOP -path */$filePath.java -exec $CODEGEN_NAME {} \\;"
}
}
diff --git a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
index 629f720..99a26dc 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ProtoLogTool.kt
@@ -24,6 +24,7 @@
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
+import java.io.OutputStream
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.jar.JarOutputStream
@@ -42,9 +43,10 @@
}
private fun processClasses(command: CommandOptions) {
- val groups = ProtoLogGroupReader()
- .loadFromJar(command.protoLogGroupsJarArg, command.protoLogGroupsClassNameArg)
- val out = FileOutputStream(command.outputSourceJarArg)
+ val groups = injector.readLogGroups(
+ command.protoLogGroupsJarArg,
+ command.protoLogGroupsClassNameArg)
+ val out = injector.fileOutputStream(command.outputSourceJarArg)
val outJar = JarOutputStream(out)
val processor = ProtoLogCallProcessor(command.protoLogClassNameArg,
command.protoLogGroupsClassNameArg, groups)
@@ -56,18 +58,18 @@
val transformer = SourceTransformer(command.protoLogImplClassNameArg,
command.protoLogCacheClassNameArg, processor)
val file = File(path)
- val text = file.readText()
+ val text = injector.readText(file)
val outSrc = try {
val code = tryParse(text, path)
if (containsProtoLogText(text, command.protoLogClassNameArg)) {
- transformer.processClass(text, path, code)
+ transformer.processClass(text, path, packagePath(file, code), code)
} else {
text
}
} catch (ex: ParsingException) {
// If we cannot parse this file, skip it (and log why). Compilation will fail
// in a subsequent build step.
- println("\n${ex.message}\n")
+ injector.reportParseError(ex)
text
}
path to outSrc
@@ -142,8 +144,9 @@
}
private fun viewerConf(command: CommandOptions) {
- val groups = ProtoLogGroupReader()
- .loadFromJar(command.protoLogGroupsJarArg, command.protoLogGroupsClassNameArg)
+ val groups = injector.readLogGroups(
+ command.protoLogGroupsJarArg,
+ command.protoLogGroupsClassNameArg)
val processor = ProtoLogCallProcessor(command.protoLogClassNameArg,
command.protoLogGroupsClassNameArg, groups)
val builder = ViewerConfigBuilder(processor)
@@ -153,18 +156,15 @@
command.javaSourceArgs.map { path ->
executor.submitCallable {
val file = File(path)
- val text = file.readText()
+ val text = injector.readText(file)
if (containsProtoLogText(text, command.protoLogClassNameArg)) {
try {
val code = tryParse(text, path)
- val pack = if (code.packageDeclaration.isPresent) code.packageDeclaration
- .get().nameAsString else ""
- val newPath = pack.replace('.', '/') + '/' + file.name
- builder.findLogCalls(code, newPath)
+ builder.findLogCalls(code, path, packagePath(file, code))
} catch (ex: ParsingException) {
// If we cannot parse this file, skip it (and log why). Compilation will fail
// in a subsequent build step.
- println("\n${ex.message}\n")
+ injector.reportParseError(ex)
null
}
} else {
@@ -177,11 +177,18 @@
executor.shutdown()
- val out = FileOutputStream(command.viewerConfigJsonArg)
+ val out = injector.fileOutputStream(command.viewerConfigJsonArg)
out.write(builder.build().toByteArray())
out.close()
}
+ private fun packagePath(file: File, code: CompilationUnit): String {
+ val pack = if (code.packageDeclaration.isPresent) code.packageDeclaration
+ .get().nameAsString else ""
+ val packagePath = pack.replace('.', '/') + '/' + file.name
+ return packagePath
+ }
+
private fun read(command: CommandOptions) {
LogParser(ViewerConfigParser())
.parse(FileInputStream(command.logProtofileArg),
@@ -190,18 +197,9 @@
@JvmStatic
fun main(args: Array<String>) {
- StaticJavaParser.setConfiguration(ParserConfiguration().apply {
- setLanguageLevel(ParserConfiguration.LanguageLevel.RAW)
- setAttributeComments(false)
- })
-
try {
val command = CommandOptions(args)
- when (command.command) {
- CommandOptions.TRANSFORM_CALLS_CMD -> processClasses(command)
- CommandOptions.GENERATE_CONFIG_CMD -> viewerConf(command)
- CommandOptions.READ_LOG_CMD -> read(command)
- }
+ invoke(command)
} catch (ex: InvalidCommandException) {
println("\n${ex.message}\n")
showHelpAndExit()
@@ -210,6 +208,36 @@
exitProcess(1)
}
}
+
+ fun invoke(command: CommandOptions) {
+ StaticJavaParser.setConfiguration(ParserConfiguration().apply {
+ setLanguageLevel(ParserConfiguration.LanguageLevel.RAW)
+ setAttributeComments(false)
+ })
+
+ when (command.command) {
+ CommandOptions.TRANSFORM_CALLS_CMD -> processClasses(command)
+ CommandOptions.GENERATE_CONFIG_CMD -> viewerConf(command)
+ CommandOptions.READ_LOG_CMD -> read(command)
+ }
+ }
+
+ var injector = object : Injector {
+ override fun fileOutputStream(file: String) = FileOutputStream(file)
+ override fun readText(file: File) = file.readText()
+ override fun readLogGroups(jarPath: String, className: String) =
+ ProtoLogGroupReader().loadFromJar(jarPath, className)
+ override fun reportParseError(ex: ParsingException) {
+ println("\n${ex.message}\n")
+ }
+ }
+
+ interface Injector {
+ fun fileOutputStream(file: String): OutputStream
+ fun readText(file: File): String
+ fun readLogGroups(jarPath: String, className: String): Map<String, LogGroup>
+ fun reportParseError(ex: ParsingException)
+ }
}
private fun <T> ExecutorService.submitCallable(f: () -> T) = submit(f)
diff --git a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
index 0ad8091..36ea411 100644
--- a/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/SourceTransformer.kt
@@ -72,7 +72,7 @@
}
val ifStmt: IfStmt
if (group.enabled) {
- val hash = CodeUtils.hash(fileName, messageString, level, group)
+ val hash = CodeUtils.hash(packagePath, messageString, level, group)
val newCall = call.clone()
if (!group.textEnabled) {
// Remove message string if text logging is not enabled by default.
@@ -97,7 +97,7 @@
if (argTypes.size != call.arguments.size - 2) {
throw InvalidProtoLogCallException(
"Number of arguments (${argTypes.size} does not mach format" +
- " string in: $call", ParsingContext(fileName, call))
+ " string in: $call", ParsingContext(path, call))
}
val blockStmt = BlockStmt()
if (argTypes.isNotEmpty()) {
@@ -214,18 +214,23 @@
StaticJavaParser.parseExpression<FieldAccessExpr>(protoLogCacheClassName)
private var processedCode: MutableList<String> = mutableListOf()
private var offsets: IntArray = IntArray(0)
- private var fileName: String = ""
+ /** The path of the file being processed, relative to $ANDROID_BUILD_TOP */
+ private var path: String = ""
+ /** The path of the file being processed, relative to the root package */
+ private var packagePath: String = ""
fun processClass(
code: String,
path: String,
+ packagePath: String,
compilationUnit: CompilationUnit =
StaticJavaParser.parse(code)
): String {
- fileName = path
+ this.path = path
+ this.packagePath = packagePath
processedCode = code.split('\n').toMutableList()
offsets = IntArray(processedCode.size)
- protoLogCallProcessor.process(compilationUnit, this, fileName)
+ protoLogCallProcessor.process(compilationUnit, this, path)
return processedCode.joinToString("\n")
}
}
diff --git a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigBuilder.kt b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigBuilder.kt
index c100826..175c71f 100644
--- a/tools/protologtool/src/com/android/protolog/tool/ViewerConfigBuilder.kt
+++ b/tools/protologtool/src/com/android/protolog/tool/ViewerConfigBuilder.kt
@@ -46,7 +46,11 @@
private val statements: MutableMap<Int, LogCall> = mutableMapOf()
private val groups: MutableSet<LogGroup> = mutableSetOf()
- fun findLogCalls(unit: CompilationUnit, fileName: String): List<Pair<LogCall, ParsingContext>> {
+ fun findLogCalls(
+ unit: CompilationUnit,
+ path: String,
+ packagePath: String
+ ): List<Pair<LogCall, ParsingContext>> {
val calls = mutableListOf<Pair<LogCall, ParsingContext>>()
val visitor = object : ProtoLogCallVisitor {
override fun processCall(
@@ -55,12 +59,12 @@
level: LogLevel,
group: LogGroup
) {
- val logCall = LogCall(messageString, level, group, fileName)
- val context = ParsingContext(fileName, call)
+ val logCall = LogCall(messageString, level, group, packagePath)
+ val context = ParsingContext(path, call)
calls.add(logCall to context)
}
}
- processor.process(unit, visitor, fileName)
+ processor.process(unit, visitor, path)
return calls
}
diff --git a/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt b/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt
new file mode 100644
index 0000000..dd8a0b1
--- /dev/null
+++ b/tools/protologtool/tests/com/android/protolog/tool/EndToEndTest.kt
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.protolog.tool
+
+import org.junit.Assert
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import java.io.ByteArrayInputStream
+import java.io.ByteArrayOutputStream
+import java.io.File
+import java.io.FileNotFoundException
+import java.io.OutputStream
+import java.util.jar.JarInputStream
+
+class EndToEndTest {
+
+ @Test
+ fun e2e_transform() {
+ val output = run(
+ src = "frameworks/base/org/example/Example.java" to """
+ package org.example;
+ import com.android.server.protolog.common.ProtoLog;
+ import static com.android.server.wm.ProtoLogGroup.GROUP;
+
+ class Example {
+ void method() {
+ String argString = "hello";
+ int argInt = 123;
+ ProtoLog.d(GROUP, "Example: %s %d", argString, argInt);
+ }
+ }
+ """.trimIndent(),
+ logGroup = LogGroup("GROUP", true, false, "TAG_GROUP"),
+ commandOptions = CommandOptions(arrayOf("transform-protolog-calls",
+ "--protolog-class", "com.android.server.protolog.common.ProtoLog",
+ "--protolog-impl-class", "com.android.server.protolog.ProtoLogImpl",
+ "--protolog-cache-class",
+ "com.android.server.protolog.ProtoLog${"\$\$"}Cache",
+ "--loggroups-class", "com.android.server.wm.ProtoLogGroup",
+ "--loggroups-jar", "not_required.jar",
+ "--output-srcjar", "out.srcjar",
+ "frameworks/base/org/example/Example.java"))
+ )
+ val outSrcJar = assertLoadSrcJar(output, "out.srcjar")
+ assertTrue(" 2066303299," in outSrcJar["frameworks/base/org/example/Example.java"]!!)
+ }
+
+ @Test
+ fun e2e_viewerConfig() {
+ val output = run(
+ src = "frameworks/base/org/example/Example.java" to """
+ package org.example;
+ import com.android.server.protolog.common.ProtoLog;
+ import static com.android.server.wm.ProtoLogGroup.GROUP;
+
+ class Example {
+ void method() {
+ String argString = "hello";
+ int argInt = 123;
+ ProtoLog.d(GROUP, "Example: %s %d", argString, argInt);
+ }
+ }
+ """.trimIndent(),
+ logGroup = LogGroup("GROUP", true, false, "TAG_GROUP"),
+ commandOptions = CommandOptions(arrayOf("generate-viewer-config",
+ "--protolog-class", "com.android.server.protolog.common.ProtoLog",
+ "--loggroups-class", "com.android.server.wm.ProtoLogGroup",
+ "--loggroups-jar", "not_required.jar",
+ "--viewer-conf", "out.json",
+ "frameworks/base/org/example/Example.java"))
+ )
+ val viewerConfigJson = assertLoadText(output, "out.json")
+ assertTrue("\"2066303299\"" in viewerConfigJson)
+ }
+
+ private fun assertLoadSrcJar(
+ outputs: Map<String, ByteArray>,
+ path: String
+ ): Map<String, String> {
+ val out = outputs[path] ?: fail("$path not in outputs (${outputs.keys})")
+
+ val sources = mutableMapOf<String, String>()
+ JarInputStream(ByteArrayInputStream(out)).use { jarStream ->
+ var entry = jarStream.nextJarEntry
+ while (entry != null) {
+ if (entry.name.endsWith(".java")) {
+ sources[entry.name] = jarStream.reader().readText()
+ }
+ entry = jarStream.nextJarEntry
+ }
+ }
+ return sources
+ }
+
+ private fun assertLoadText(outputs: Map<String, ByteArray>, path: String): String {
+ val out = outputs[path] ?: fail("$path not in outputs (${outputs.keys})")
+ return out.toString(Charsets.UTF_8)
+ }
+
+ fun run(
+ src: Pair<String, String>,
+ logGroup: LogGroup,
+ commandOptions: CommandOptions
+ ): Map<String, ByteArray> {
+ val outputs = mutableMapOf<String, ByteArrayOutputStream>()
+
+ ProtoLogTool.injector = object : ProtoLogTool.Injector {
+ override fun fileOutputStream(file: String): OutputStream =
+ ByteArrayOutputStream().also { outputs[file] = it }
+
+ override fun readText(file: File): String {
+ if (file.path == src.first) {
+ return src.second
+ }
+ throw FileNotFoundException("expected: ${src.first}, but was $file")
+ }
+
+ override fun readLogGroups(jarPath: String, className: String) = mapOf(
+ logGroup.name to logGroup)
+
+ override fun reportParseError(ex: ParsingException) = throw AssertionError(ex)
+ }
+
+ ProtoLogTool.invoke(commandOptions)
+
+ return outputs.mapValues { it.value.toByteArray() }
+ }
+
+ fun fail(message: String): Nothing = Assert.fail(message) as Nothing
+}
diff --git a/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt b/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt
index 6f5955c..4f2be328 100644
--- a/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt
+++ b/tools/protologtool/tests/com/android/protolog/tool/SourceTransformerTest.kt
@@ -186,7 +186,7 @@
invocation.arguments[0] as CompilationUnit
}
- val out = sourceJarWriter.processClass(TEST_CODE, PATH, code)
+ val out = sourceJarWriter.processClass(TEST_CODE, PATH, PATH, code)
code = StaticJavaParser.parse(out)
val ifStmts = code.findAll(IfStmt::class.java)
@@ -228,7 +228,7 @@
invocation.arguments[0] as CompilationUnit
}
- val out = sourceJarWriter.processClass(TEST_CODE_MULTICALLS, PATH, code)
+ val out = sourceJarWriter.processClass(TEST_CODE_MULTICALLS, PATH, PATH, code)
code = StaticJavaParser.parse(out)
val ifStmts = code.findAll(IfStmt::class.java)
@@ -266,7 +266,7 @@
invocation.arguments[0] as CompilationUnit
}
- val out = sourceJarWriter.processClass(TEST_CODE_MULTILINE, PATH, code)
+ val out = sourceJarWriter.processClass(TEST_CODE_MULTILINE, PATH, PATH, code)
code = StaticJavaParser.parse(out)
val ifStmts = code.findAll(IfStmt::class.java)
@@ -303,7 +303,7 @@
invocation.arguments[0] as CompilationUnit
}
- val out = sourceJarWriter.processClass(TEST_CODE_NO_PARAMS, PATH, code)
+ val out = sourceJarWriter.processClass(TEST_CODE_NO_PARAMS, PATH, PATH, code)
code = StaticJavaParser.parse(out)
val ifStmts = code.findAll(IfStmt::class.java)
@@ -337,7 +337,7 @@
invocation.arguments[0] as CompilationUnit
}
- val out = sourceJarWriter.processClass(TEST_CODE, PATH, code)
+ val out = sourceJarWriter.processClass(TEST_CODE, PATH, PATH, code)
code = StaticJavaParser.parse(out)
val ifStmts = code.findAll(IfStmt::class.java)
@@ -375,7 +375,7 @@
invocation.arguments[0] as CompilationUnit
}
- val out = sourceJarWriter.processClass(TEST_CODE_MULTILINE, PATH, code)
+ val out = sourceJarWriter.processClass(TEST_CODE_MULTILINE, PATH, PATH, code)
code = StaticJavaParser.parse(out)
val ifStmts = code.findAll(IfStmt::class.java)
@@ -413,7 +413,7 @@
invocation.arguments[0] as CompilationUnit
}
- val out = sourceJarWriter.processClass(TEST_CODE, PATH, code)
+ val out = sourceJarWriter.processClass(TEST_CODE, PATH, PATH, code)
code = StaticJavaParser.parse(out)
val ifStmts = code.findAll(IfStmt::class.java)
@@ -439,7 +439,7 @@
invocation.arguments[0] as CompilationUnit
}
- val out = sourceJarWriter.processClass(TEST_CODE_MULTILINE, PATH, code)
+ val out = sourceJarWriter.processClass(TEST_CODE_MULTILINE, PATH, PATH, code)
code = StaticJavaParser.parse(out)
val ifStmts = code.findAll(IfStmt::class.java)
diff --git a/wifi/java/android/net/wifi/ISoftApCallback.aidl b/wifi/java/android/net/wifi/ISoftApCallback.aidl
index 8a252dd..452a655 100644
--- a/wifi/java/android/net/wifi/ISoftApCallback.aidl
+++ b/wifi/java/android/net/wifi/ISoftApCallback.aidl
@@ -15,6 +15,7 @@
*/
package android.net.wifi;
+import android.net.wifi.SoftApInfo;
import android.net.wifi.WifiClient;
@@ -43,4 +44,11 @@
* @param clients the currently connected clients
*/
void onConnectedClientsChanged(in List<WifiClient> clients);
+
+ /**
+ * Service to manager callback providing information of softap.
+ *
+ * @param softApInfo is the softap information. {@link SoftApInfo}
+ */
+ void onInfoChanged(in SoftApInfo softApInfo);
}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 19be132..023df70 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -34,6 +34,7 @@
import android.net.wifi.ITxPacketCountListener;
import android.net.wifi.IOnWifiUsabilityStatsListener;
import android.net.wifi.ScanResult;
+import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiActivityEnergyInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
@@ -142,7 +143,8 @@
boolean stopSoftAp();
- int startLocalOnlyHotspot(in ILocalOnlyHotspotCallback callback, String packageName);
+ int startLocalOnlyHotspot(in ILocalOnlyHotspotCallback callback, String packageName,
+ in SoftApConfiguration customConfig);
void stopLocalOnlyHotspot();
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index c0c0361..aa895a6 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -16,11 +16,15 @@
package android.net.wifi;
+import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -223,11 +227,86 @@
*/
public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4;
- /**
- * AP Channel bandwidth; one of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ},
- * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ}
- * or {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ}.
- */
+ /**
+ * Wi-Fi unknown standard
+ */
+ public static final int WIFI_STANDARD_UNKNOWN = 0;
+
+ /**
+ * Wi-Fi 802.11a/b/g
+ */
+ public static final int WIFI_STANDARD_LEGACY = 1;
+
+ /**
+ * Wi-Fi 802.11n
+ */
+ public static final int WIFI_STANDARD_11N = 4;
+
+ /**
+ * Wi-Fi 802.11ac
+ */
+ public static final int WIFI_STANDARD_11AC = 5;
+
+ /**
+ * Wi-Fi 802.11ax
+ */
+ public static final int WIFI_STANDARD_11AX = 6;
+
+ /** @hide */
+ @IntDef(prefix = { "WIFI_STANDARD_" }, value = {
+ WIFI_STANDARD_UNKNOWN,
+ WIFI_STANDARD_LEGACY,
+ WIFI_STANDARD_11N,
+ WIFI_STANDARD_11AC,
+ WIFI_STANDARD_11AX
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface WifiStandard{}
+
+ /**
+ * AP wifi standard.
+ */
+ private @WifiStandard int mWifiStandard;
+
+ /**
+ * return the AP wifi standard.
+ */
+ public @WifiStandard int getWifiStandard() {
+ return mWifiStandard;
+ }
+
+ /**
+ * sets the AP wifi standard.
+ * @hide
+ */
+ public void setWifiStandard(@WifiStandard int standard) {
+ mWifiStandard = standard;
+ }
+
+ /**
+ * Convert Wi-Fi standard to string
+ */
+ private static @Nullable String wifiStandardToString(@WifiStandard int standard) {
+ switch(standard) {
+ case WIFI_STANDARD_LEGACY:
+ return "legacy";
+ case WIFI_STANDARD_11N:
+ return "11n";
+ case WIFI_STANDARD_11AC:
+ return "11ac";
+ case WIFI_STANDARD_11AX:
+ return "11ax";
+ case WIFI_STANDARD_UNKNOWN:
+ return "unknown";
+ }
+ return null;
+ }
+
+ /**
+ * AP Channel bandwidth; one of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ},
+ * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ}
+ * or {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ}.
+ */
public int channelWidth;
/**
@@ -465,9 +544,16 @@
public static final int EID_VHT_OPERATION = 192;
@UnsupportedAppUsage
public static final int EID_VSA = 221;
+ public static final int EID_EXTENSION_PRESENT = 255;
+
+ /**
+ * Extension IDs
+ */
+ public static final int EID_EXT_HE_OPERATION = 36;
@UnsupportedAppUsage
public int id;
+ public int idExt;
@UnsupportedAppUsage
public byte[] bytes;
@@ -476,6 +562,7 @@
public InformationElement(InformationElement rhs) {
this.id = rhs.id;
+ this.idExt = rhs.idExt;
this.bytes = rhs.bytes.clone();
}
}
@@ -541,6 +628,7 @@
this.carrierApEapType = UNSPECIFIED;
this.carrierName = null;
this.radioChainInfos = null;
+ this.mWifiStandard = WIFI_STANDARD_UNKNOWN;
}
/** {@hide} */
@@ -563,6 +651,7 @@
this.carrierApEapType = UNSPECIFIED;
this.carrierName = null;
this.radioChainInfos = null;
+ this.mWifiStandard = WIFI_STANDARD_UNKNOWN;
}
/** {@hide} */
@@ -592,6 +681,7 @@
this.carrierApEapType = UNSPECIFIED;
this.carrierName = null;
this.radioChainInfos = null;
+ this.mWifiStandard = WIFI_STANDARD_UNKNOWN;
}
/** {@hide} */
@@ -633,6 +723,7 @@
carrierApEapType = source.carrierApEapType;
carrierName = source.carrierName;
radioChainInfos = source.radioChainInfos;
+ this.mWifiStandard = source.mWifiStandard;
}
}
@@ -671,6 +762,7 @@
sb.append(", ChannelBandwidth: ").append(channelWidth);
sb.append(", centerFreq0: ").append(centerFreq0);
sb.append(", centerFreq1: ").append(centerFreq1);
+ sb.append(", standard: ").append(wifiStandardToString(mWifiStandard));
sb.append(", 80211mcResponder: ");
sb.append(((flags & FLAG_80211mc_RESPONDER) != 0) ? "is supported" : "is not supported");
sb.append(", Carrier AP: ").append(isCarrierAp ? "yes" : "no");
@@ -706,6 +798,7 @@
dest.writeInt(channelWidth);
dest.writeInt(centerFreq0);
dest.writeInt(centerFreq1);
+ dest.writeInt(mWifiStandard);
dest.writeLong(seen);
dest.writeInt(untrusted ? 1 : 0);
dest.writeInt(numUsage);
@@ -717,6 +810,7 @@
dest.writeInt(informationElements.length);
for (int i = 0; i < informationElements.length; i++) {
dest.writeInt(informationElements[i].id);
+ dest.writeInt(informationElements[i].idExt);
dest.writeInt(informationElements[i].bytes.length);
dest.writeByteArray(informationElements[i].bytes);
}
@@ -787,6 +881,7 @@
fixed with flags below */
);
+ sr.mWifiStandard = in.readInt();
sr.seen = in.readLong();
sr.untrusted = in.readInt() != 0;
sr.numUsage = in.readInt();
@@ -799,6 +894,7 @@
for (int i = 0; i < n; i++) {
sr.informationElements[i] = new InformationElement();
sr.informationElements[i].id = in.readInt();
+ sr.informationElements[i].idExt = in.readInt();
int len = in.readInt();
sr.informationElements[i].bytes = new byte[len];
in.readByteArray(sr.informationElements[i].bytes);
diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.aidl b/wifi/java/android/net/wifi/SoftApConfiguration.aidl
new file mode 100644
index 0000000..1d06f45
--- /dev/null
+++ b/wifi/java/android/net/wifi/SoftApConfiguration.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+parcelable SoftApConfiguration;
\ No newline at end of file
diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java
new file mode 100644
index 0000000..4cc8653
--- /dev/null
+++ b/wifi/java/android/net/wifi/SoftApConfiguration.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.net.MacAddress;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+
+/**
+ * WiFi configuration for a soft access point (a.k.a. Soft AP, SAP, Hotspot).
+ *
+ * This is input for the framework provided by a client app, i.e. it exposes knobs to instruct the
+ * framework how it should open a hotspot. It is not meant to describe the network as it will be
+ * seen by clients; this role is currently served by {@link WifiConfiguration} (see
+ * {@link WifiManager.LocalOnlyHotspotReservation#getWifiConfiguration()}).
+ *
+ * System apps can use this to configure a local-only hotspot using
+ * {@link WifiManager#startLocalOnlyHotspot(SoftApConfiguration, Executor,
+ * WifiManager.LocalOnlyHotspotCallback)}.
+ *
+ * Instances of this class are immutable; use {@link SoftApConfiguration.Builder} and its methods to
+ * create a new instance.
+ *
+ * @hide
+ */
+@SystemApi
+public final class SoftApConfiguration implements Parcelable {
+ /**
+ * SSID for the AP, or null for a framework-determined SSID.
+ */
+ private final @Nullable String mSsid;
+ /**
+ * BSSID for the AP, or null to use a framework-determined BSSID.
+ */
+ private final @Nullable MacAddress mBssid;
+ /**
+ * Pre-shared key for WPA2-PSK encryption (non-null enables WPA2-PSK).
+ */
+ private final @Nullable String mWpa2Passphrase;
+
+ /** Private constructor for Builder and Parcelable implementation. */
+ private SoftApConfiguration(
+ @Nullable String ssid, @Nullable MacAddress bssid, String wpa2Passphrase) {
+ mSsid = ssid;
+ mBssid = bssid;
+ mWpa2Passphrase = wpa2Passphrase;
+ }
+
+ @Override
+ public boolean equals(Object otherObj) {
+ if (this == otherObj) {
+ return true;
+ }
+ if (!(otherObj instanceof SoftApConfiguration)) {
+ return false;
+ }
+ SoftApConfiguration other = (SoftApConfiguration) otherObj;
+ return Objects.equals(mSsid, other.mSsid)
+ && Objects.equals(mBssid, other.mBssid)
+ && Objects.equals(mWpa2Passphrase, other.mWpa2Passphrase);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSsid, mBssid, mWpa2Passphrase);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeString(mSsid);
+ dest.writeParcelable(mBssid, flags);
+ dest.writeString(mWpa2Passphrase);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @NonNull
+ public static final Creator<SoftApConfiguration> CREATOR = new Creator<SoftApConfiguration>() {
+ @Override
+ public SoftApConfiguration createFromParcel(Parcel in) {
+ return new SoftApConfiguration(
+ in.readString(),
+ in.readParcelable(MacAddress.class.getClassLoader()),
+ in.readString());
+ }
+
+ @Override
+ public SoftApConfiguration[] newArray(int size) {
+ return new SoftApConfiguration[size];
+ }
+ };
+
+ @Nullable
+ public String getSsid() {
+ return mSsid;
+ }
+
+ @Nullable
+ public MacAddress getBssid() {
+ return mBssid;
+ }
+
+ @Nullable
+ public String getWpa2Passphrase() {
+ return mWpa2Passphrase;
+ }
+
+ /**
+ * Builds a {@link SoftApConfiguration}, which allows an app to configure various aspects of a
+ * Soft AP.
+ *
+ * All fields are optional. By default, SSID and BSSID are automatically chosen by the
+ * framework, and an open network is created.
+ */
+ public static final class Builder {
+ private String mSsid;
+ private MacAddress mBssid;
+ private String mWpa2Passphrase;
+
+ /**
+ * Constructs a Builder with default values (see {@link Builder}).
+ */
+ public Builder() {
+ mSsid = null;
+ mBssid = null;
+ mWpa2Passphrase = null;
+ }
+
+ /**
+ * Constructs a Builder initialized from an existing {@link SoftApConfiguration} instance.
+ */
+ public Builder(@NonNull SoftApConfiguration other) {
+ Objects.requireNonNull(other);
+
+ mSsid = other.mSsid;
+ mBssid = other.mBssid;
+ mWpa2Passphrase = other.mWpa2Passphrase;
+ }
+
+ /**
+ * Builds the {@link SoftApConfiguration}.
+ *
+ * @return A new {@link SoftApConfiguration}, as configured by previous method calls.
+ */
+ @NonNull
+ public SoftApConfiguration build() {
+ return new SoftApConfiguration(mSsid, mBssid, mWpa2Passphrase);
+ }
+
+ /**
+ * Specifies an SSID for the AP.
+ *
+ * @param ssid SSID of valid Unicode characters, or null to have the SSID automatically
+ * chosen by the framework.
+ * @return Builder for chaining.
+ * @throws IllegalArgumentException when the SSID is empty or not valid Unicode.
+ */
+ @NonNull
+ public Builder setSsid(@Nullable String ssid) {
+ if (ssid != null) {
+ Preconditions.checkStringNotEmpty(ssid);
+ Preconditions.checkArgument(StandardCharsets.UTF_8.newEncoder().canEncode(ssid));
+ }
+ mSsid = ssid;
+ return this;
+ }
+
+ /**
+ * Specifies a BSSID for the AP.
+ *
+ * @param bssid BSSID, or null to have the BSSID chosen by the framework. The caller is
+ * responsible for avoiding collisions.
+ * @return Builder for chaining.
+ * @throws IllegalArgumentException when the given BSSID is the all-zero or broadcast MAC
+ * address.
+ */
+ @NonNull
+ public Builder setBssid(@Nullable MacAddress bssid) {
+ if (bssid != null) {
+ Preconditions.checkArgument(!bssid.equals(MacAddress.ALL_ZEROS_ADDRESS));
+ Preconditions.checkArgument(!bssid.equals(MacAddress.BROADCAST_ADDRESS));
+ }
+ mBssid = bssid;
+ return this;
+ }
+
+ /**
+ * Specifies that this AP should use WPA2-PSK with the given passphrase. When set to null
+ * and no other encryption method is configured, an open network is created.
+ *
+ * @param passphrase The passphrase to use, or null to unset a previously-set WPA2-PSK
+ * configuration.
+ * @return Builder for chaining.
+ * @throws IllegalArgumentException when the passphrase is the empty string
+ */
+ @NonNull
+ public Builder setWpa2Passphrase(@Nullable String passphrase) {
+ if (passphrase != null) {
+ Preconditions.checkStringNotEmpty(passphrase);
+ }
+ mWpa2Passphrase = passphrase;
+ return this;
+ }
+ }
+}
diff --git a/wifi/java/android/net/wifi/SoftApInfo.aidl b/wifi/java/android/net/wifi/SoftApInfo.aidl
new file mode 100644
index 0000000..d4551cf
--- /dev/null
+++ b/wifi/java/android/net/wifi/SoftApInfo.aidl
@@ -0,0 +1,20 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+parcelable SoftApInfo;
+
diff --git a/wifi/java/android/net/wifi/SoftApInfo.java b/wifi/java/android/net/wifi/SoftApInfo.java
new file mode 100644
index 0000000..375a977
--- /dev/null
+++ b/wifi/java/android/net/wifi/SoftApInfo.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * A class representing information about SoftAp.
+ * {@see WifiManager}
+ *
+ * @hide
+ */
+@SystemApi
+public final class SoftApInfo implements Parcelable {
+
+ /**
+ * AP Channel bandwidth is invalid.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_INVALID = 0;
+
+ /**
+ * AP Channel bandwidth is 20 MHZ but no HT.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_20MHZ_NOHT = 1;
+
+ /**
+ * AP Channel bandwidth is 20 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_20MHZ = 2;
+
+ /**
+ * AP Channel bandwidth is 40 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_40MHZ = 3;
+
+ /**
+ * AP Channel bandwidth is 80 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_80MHZ = 4;
+
+ /**
+ * AP Channel bandwidth is 160 MHZ, but 80MHZ + 80MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 5;
+
+ /**
+ * AP Channel bandwidth is 160 MHZ.
+ *
+ * @see #getBandwidth()
+ */
+ public static final int CHANNEL_WIDTH_160MHZ = 6;
+
+ /**
+ * @hide
+ */
+ @IntDef(prefix = { "CHANNEL_WIDTH_" }, value = {
+ CHANNEL_WIDTH_INVALID,
+ CHANNEL_WIDTH_20MHZ_NOHT,
+ CHANNEL_WIDTH_20MHZ,
+ CHANNEL_WIDTH_40MHZ,
+ CHANNEL_WIDTH_80MHZ,
+ CHANNEL_WIDTH_80MHZ_PLUS_MHZ,
+ CHANNEL_WIDTH_160MHZ,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Bandwidth {}
+
+
+ /** The frequency which AP resides on. */
+ private int mFrequency = 0;
+
+ @Bandwidth
+ private int mBandwidth = CHANNEL_WIDTH_INVALID;
+
+ /**
+ * Get the frequency which AP resides on.
+ */
+ public int getFrequency() {
+ return mFrequency;
+ }
+
+ /**
+ * Set the frequency which AP resides on.
+ * @hide
+ */
+ public void setFrequency(int freq) {
+ mFrequency = freq;
+ }
+
+ /**
+ * Get AP Channel bandwidth.
+ *
+ * @return One of {@link #CHANNEL_WIDTH_20MHZ}, {@link #CHANNEL_WIDTH_40MHZ},
+ * {@link #CHANNEL_WIDTH_80MHZ}, {@link #CHANNEL_WIDTH_160MHZ},
+ * {@link #CHANNEL_WIDTH_80MHZ_PLUS_MHZ} or {@link #CHANNEL_WIDTH_UNKNOWN}.
+ */
+ @Bandwidth
+ public int getBandwidth() {
+ return mBandwidth;
+ }
+
+ /**
+ * Set AP Channel bandwidth.
+ * @hide
+ */
+ public void setBandwidth(@Bandwidth int bandwidth) {
+ mBandwidth = bandwidth;
+ }
+
+ /**
+ * @hide
+ */
+ public SoftApInfo(@Nullable SoftApInfo source) {
+ if (source != null) {
+ mFrequency = source.mFrequency;
+ mBandwidth = source.mBandwidth;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public SoftApInfo() {
+ }
+
+ @Override
+ /** Implement the Parcelable interface. */
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ /** Implement the Parcelable interface */
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mFrequency);
+ dest.writeInt(mBandwidth);
+ }
+
+ @NonNull
+ /** Implement the Parcelable interface */
+ public static final Creator<SoftApInfo> CREATOR = new Creator<SoftApInfo>() {
+ public SoftApInfo createFromParcel(Parcel in) {
+ SoftApInfo info = new SoftApInfo();
+ info.mFrequency = in.readInt();
+ info.mBandwidth = in.readInt();
+ return info;
+ }
+
+ public SoftApInfo[] newArray(int size) {
+ return new SoftApInfo[size];
+ }
+ };
+
+ @NonNull
+ @Override
+ public String toString() {
+ return "SoftApInfo{"
+ + "bandwidth= " + mBandwidth
+ + ",frequency= " + mFrequency
+ + '}';
+ }
+
+ @Override
+ public boolean equals(@NonNull Object o) {
+ if (this == o) return true;
+ if (!(o instanceof SoftApInfo)) return false;
+ SoftApInfo softApInfo = (SoftApInfo) o;
+ return mFrequency == softApInfo.mFrequency
+ && mBandwidth == softApInfo.mBandwidth;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mFrequency, mBandwidth);
+ }
+}
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 3dc5a62..30c24d3 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -34,6 +34,7 @@
import android.os.Parcelable;
import android.os.SystemClock;
import android.os.UserHandle;
+import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.BackupUtils;
import android.util.Log;
@@ -730,6 +731,14 @@
public String lastUpdateName;
/**
+ * The carrier ID identifies the operator who provides this network configuration.
+ * see {@link TelephonyManager#getSimCarrierId()}
+ * @hide
+ */
+ @SystemApi
+ public int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+
+ /**
* @hide
* Status of user approval for connection
*/
@@ -1850,6 +1859,7 @@
.append(" PRIO: ").append(this.priority)
.append(" HIDDEN: ").append(this.hiddenSSID)
.append(" PMF: ").append(this.requirePMF)
+ .append("CarrierId: ").append(this.carrierId)
.append('\n');
@@ -2443,6 +2453,7 @@
randomizedMacExpirationTimeMs = source.randomizedMacExpirationTimeMs;
requirePMF = source.requirePMF;
updateIdentifier = source.updateIdentifier;
+ carrierId = source.carrierId;
}
}
@@ -2517,6 +2528,7 @@
dest.writeInt(macRandomizationSetting);
dest.writeInt(osu ? 1 : 0);
dest.writeLong(randomizedMacExpirationTimeMs);
+ dest.writeInt(carrierId);
}
/** Implement the Parcelable interface {@hide} */
@@ -2593,6 +2605,7 @@
config.macRandomizationSetting = in.readInt();
config.osu = in.readInt() != 0;
config.randomizedMacExpirationTimeMs = in.readLong();
+ config.carrierId = in.readInt();
return config;
}
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index f8c20111..7b99a2b 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -1263,4 +1263,23 @@
public @Ocsp int getOcsp() {
return mOcsp;
}
+
+ /**
+ * If the current authentication method needs SIM card.
+ * @return true if the credential information require SIM card for current authentication
+ * method, otherwise it returns false.
+ * @hide
+ */
+ public boolean requireSimCredential() {
+ if (mEapMethod == Eap.SIM || mEapMethod == Eap.AKA || mEapMethod == Eap.AKA_PRIME) {
+ return true;
+ }
+ if (mEapMethod == Eap.PEAP) {
+ if (mPhase2Method == Phase2.SIM || mPhase2Method == Phase2.AKA
+ || mPhase2Method == Phase2.AKA_PRIME) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index 62ba95d..86e5122 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -16,7 +16,6 @@
package android.net.wifi;
-import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -28,8 +27,6 @@
import android.os.Parcelable;
import android.text.TextUtils;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -99,45 +96,9 @@
private int mRssi;
/**
- * Wi-Fi unknown technology
+ * Wi-Fi standard for the connection
*/
- public static final int WIFI_TECHNOLOGY_UNKNOWN = 0;
-
- /**
- * Wi-Fi 802.11a/b/g
- */
- public static final int WIFI_TECHNOLOGY_LEGACY = 1;
-
- /**
- * Wi-Fi 802.11n
- */
- public static final int WIFI_TECHNOLOGY_11N = 4;
-
- /**
- * Wi-Fi 802.11ac
- */
- public static final int WIFI_TECHNOLOGY_11AC = 5;
-
- /**
- * Wi-Fi 802.11ax
- */
- public static final int WIFI_TECHNOLOGY_11AX = 6;
-
- /** @hide */
- @IntDef(prefix = { "WIFI_TECHNOLOGY_" }, value = {
- WIFI_TECHNOLOGY_UNKNOWN,
- WIFI_TECHNOLOGY_LEGACY,
- WIFI_TECHNOLOGY_11N,
- WIFI_TECHNOLOGY_11AC,
- WIFI_TECHNOLOGY_11AX
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface WifiTechnology{}
-
- /**
- * Wi-Fi technology for the connection
- */
- private @WifiTechnology int mWifiTechnology;
+ private @ScanResult.WifiStandard int mWifiStandard;
/**
* The unit in which links speeds are expressed.
@@ -330,7 +291,7 @@
txSuccessRate = source.txSuccessRate;
rxSuccessRate = source.rxSuccessRate;
score = source.score;
- mWifiTechnology = source.mWifiTechnology;
+ mWifiStandard = source.mWifiStandard;
}
}
@@ -419,19 +380,19 @@
}
/**
- * Sets the Wi-Fi technology
+ * Sets the Wi-Fi standard
* @hide
*/
- public void setWifiTechnology(@WifiTechnology int wifiTechnology) {
- mWifiTechnology = wifiTechnology;
+ public void setWifiStandard(@ScanResult.WifiStandard int wifiStandard) {
+ mWifiStandard = wifiStandard;
}
/**
- * Get connection Wi-Fi technology
- * @return the connection Wi-Fi technology
+ * Get connection Wi-Fi standard
+ * @return the connection Wi-Fi standard
*/
- public @WifiTechnology int getWifiTechnology() {
- return mWifiTechnology;
+ public @ScanResult.WifiStandard int getWifiStandard() {
+ return mWifiStandard;
}
/**
@@ -740,7 +701,7 @@
.append(", MAC: ").append(mMacAddress == null ? none : mMacAddress)
.append(", Supplicant state: ")
.append(mSupplicantState == null ? none : mSupplicantState)
- .append(", Wi-Fi technology: ").append(mWifiTechnology)
+ .append(", Wi-Fi standard: ").append(mWifiStandard)
.append(", RSSI: ").append(mRssi)
.append(", Link speed: ").append(mLinkSpeed).append(LINK_SPEED_UNITS)
.append(", Tx Link speed: ").append(mTxLinkSpeed).append(LINK_SPEED_UNITS)
@@ -796,7 +757,7 @@
dest.writeString(mNetworkSuggestionOrSpecifierPackageName);
dest.writeString(mFqdn);
dest.writeString(mProviderFriendlyName);
- dest.writeInt(mWifiTechnology);
+ dest.writeInt(mWifiStandard);
}
/** Implement the Parcelable interface {@hide} */
@@ -838,7 +799,7 @@
info.mNetworkSuggestionOrSpecifierPackageName = in.readString();
info.mFqdn = in.readString();
info.mProviderFriendlyName = in.readString();
- info.mWifiTechnology = in.readInt();
+ info.mWifiStandard = in.readInt();
return info;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 8f71b0b..8108fef 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -71,6 +71,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
@@ -2747,13 +2748,6 @@
}
}
- private Executor executorForHandler(@Nullable Handler handler) {
- if (handler == null) {
- return mContext.getMainExecutor();
- }
- return new HandlerExecutor(handler);
- }
-
/**
* Request a local only hotspot that an application can use to communicate between co-located
* devices connected to the created WiFi hotspot. The network created by this method will not
@@ -2809,9 +2803,59 @@
* @param handler Handler to be used for callbacks. If the caller passes a null Handler, the
* main thread will be used.
*/
+ @RequiresPermission(allOf = {
+ android.Manifest.permission.CHANGE_WIFI_STATE,
+ android.Manifest.permission.ACCESS_FINE_LOCATION})
public void startLocalOnlyHotspot(LocalOnlyHotspotCallback callback,
@Nullable Handler handler) {
- Executor executor = executorForHandler(handler);
+ Executor executor = handler == null ? null : new HandlerExecutor(handler);
+ startLocalOnlyHotspotInternal(null, executor, callback);
+ }
+
+ /**
+ * Starts a local-only hotspot with a specific configuration applied. See
+ * {@link #startLocalOnlyHotspot(LocalOnlyHotspotCallback, Handler)}.
+ *
+ * Applications need either {@link android.Manifest.permission#NETWORK_SETUP_WIZARD} or
+ * {@link android.Manifest.permission#NETWORK_SETTINGS} to call this method.
+ *
+ * Since custom configuration settings may be incompatible with each other, the hotspot started
+ * through this method cannot coexist with another hotspot created through
+ * startLocalOnlyHotspot. If this is attempted, the first hotspot request wins and others
+ * receive {@link LocalOnlyHotspotCallback#ERROR_GENERIC} through
+ * {@link LocalOnlyHotspotCallback#onFailed}.
+ *
+ * @param config Custom configuration for the hotspot. See {@link SoftApConfiguration}.
+ * @param executor Executor to run callback methods on, or null to use the main thread.
+ * @param callback Callback object for updates about hotspot status, or null for no updates.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.NETWORK_SETTINGS,
+ android.Manifest.permission.NETWORK_SETUP_WIZARD})
+ public void startLocalOnlyHotspot(@NonNull SoftApConfiguration config,
+ @Nullable Executor executor,
+ @Nullable LocalOnlyHotspotCallback callback) {
+ Objects.requireNonNull(config);
+ startLocalOnlyHotspotInternal(config, executor, callback);
+ }
+
+ /**
+ * Common implementation of both configurable and non-configurable LOHS.
+ *
+ * @param config App-specified configuration, or null. When present, additional privileges are
+ * required, and the hotspot cannot be shared with other clients.
+ * @param executor Executor to run callback methods on, or null to use the main thread.
+ * @param callback Callback object for updates about hotspot status, or null for no updates.
+ */
+ private void startLocalOnlyHotspotInternal(
+ @Nullable SoftApConfiguration config,
+ @Nullable Executor executor,
+ @Nullable LocalOnlyHotspotCallback callback) {
+ if (executor == null) {
+ executor = mContext.getMainExecutor();
+ }
synchronized (mLock) {
LocalOnlyHotspotCallbackProxy proxy =
new LocalOnlyHotspotCallbackProxy(this, executor, callback);
@@ -2821,7 +2865,7 @@
throw new RemoteException("Wifi service is not running");
}
String packageName = mContext.getOpPackageName();
- int returnCode = iWifiManager.startLocalOnlyHotspot(proxy, packageName);
+ int returnCode = iWifiManager.startLocalOnlyHotspot(proxy, packageName, config);
if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) {
// Send message to the proxy to make sure we call back on the correct thread
proxy.onHotspotFailed(returnCode);
@@ -2902,7 +2946,8 @@
*/
public void watchLocalOnlyHotspot(LocalOnlyHotspotObserver observer,
@Nullable Handler handler) {
- Executor executor = executorForHandler(handler);
+ Executor executor = handler == null ? mContext.getMainExecutor()
+ : new HandlerExecutor(handler);
synchronized (mLock) {
mLOHSObserverProxy =
new LocalOnlyHotspotObserverProxy(this, executor, observer);
@@ -3270,6 +3315,15 @@
* @param clients the currently connected clients
*/
void onConnectedClientsChanged(@NonNull List<WifiClient> clients);
+
+ /**
+ * Called when information of softap changes.
+ *
+ * @param softApInfo is the softap information. {@link SoftApInfo}
+ */
+ default void onInfoChanged(@NonNull SoftApInfo softApInfo) {
+ // Do nothing: can be updated to add SoftApInfo details (e.g. channel) to the UI.
+ }
}
/**
@@ -3309,6 +3363,16 @@
mCallback.onConnectedClientsChanged(clients);
});
}
+
+ @Override
+ public void onInfoChanged(SoftApInfo softApInfo) {
+ if (mVerboseLoggingEnabled) {
+ Log.v(TAG, "SoftApCallbackProxy: onInfoChange: softApInfo=" + softApInfo);
+ }
+ mHandler.post(() -> {
+ mCallback.onInfoChanged(softApInfo);
+ });
+ }
}
/**
@@ -3484,10 +3548,12 @@
*
* @param manager WifiManager
* @param executor Executor for delivering callbacks.
- * @param callback LocalOnlyHotspotCallback to notify the calling application.
+ * @param callback LocalOnlyHotspotCallback to notify the calling application, or null.
*/
- LocalOnlyHotspotCallbackProxy(WifiManager manager, Executor executor,
- LocalOnlyHotspotCallback callback) {
+ LocalOnlyHotspotCallbackProxy(
+ @NonNull WifiManager manager,
+ @NonNull Executor executor,
+ @Nullable LocalOnlyHotspotCallback callback) {
mWifiManager = new WeakReference<>(manager);
mExecutor = executor;
mCallback = callback;
@@ -3505,6 +3571,7 @@
}
final LocalOnlyHotspotReservation reservation =
manager.new LocalOnlyHotspotReservation(config);
+ if (mCallback == null) return;
mExecutor.execute(() -> mCallback.onStarted(reservation));
}
@@ -3514,6 +3581,7 @@
if (manager == null) return;
Log.w(TAG, "LocalOnlyHotspotCallbackProxy: hotspot stopped");
+ if (mCallback == null) return;
mExecutor.execute(() -> mCallback.onStopped());
}
@@ -3524,6 +3592,7 @@
Log.w(TAG, "LocalOnlyHotspotCallbackProxy: failed to start. reason: "
+ reason);
+ if (mCallback == null) return;
mExecutor.execute(() -> mCallback.onFailed(reason));
}
}
@@ -5190,16 +5259,18 @@
/**
* Add a listener for Scan Results. See {@link ScanResultsListener}.
* Caller will receive the event when scan results are available.
- * Caller should use {@link WifiManager#getScanResults()} to get the scan results.
+ * Caller should use {@link WifiManager#getScanResults()} requires
+ * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} to get the scan results.
* Caller can remove a previously registered listener using
* {@link WifiManager#removeScanResultsListener(ScanResultsListener)}
+ * Same caller can add multiple listeners.
* <p>
* Applications should have the
* {@link android.Manifest.permission#ACCESS_WIFI_STATE} permission. Callers
* without the permission will trigger a {@link java.lang.SecurityException}.
* <p>
*
- * @param executor The executor to execute the listener of the {@code listener} object.
+ * @param executor The executor to execute the listener of the {@code listener} object.
* @param listener listener for Scan Results events
*/
@@ -5217,7 +5288,7 @@
iWifiManager.registerScanResultsListener(
new Binder(),
new ScanResultsListenerProxy(executor, listener),
- mContext.getOpPackageName().hashCode());
+ listener.hashCode());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -5239,7 +5310,7 @@
if (iWifiManager == null) {
throw new RemoteException("Wifi service is not running");
}
- iWifiManager.unregisterScanResultsListener(mContext.getOpPackageName().hashCode());
+ iWifiManager.unregisterScanResultsListener(listener.hashCode());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 9b529ce..246e96f 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -21,12 +21,15 @@
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.net.MacAddress;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
+import android.telephony.TelephonyManager;
import android.text.TextUtils;
import java.nio.charset.CharsetEncoder;
@@ -107,6 +110,12 @@
*/
private int mPriority;
+ /**
+ * The carrier ID identifies the operator who provides this network configuration.
+ * see {@link TelephonyManager#getSimCarrierId()}
+ */
+ private int mCarrierId;
+
public Builder() {
mSsid = null;
mBssid = null;
@@ -121,6 +130,7 @@
mIsUserInteractionRequired = false;
mIsMetered = false;
mPriority = UNASSIGNED_PRIORITY;
+ mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
}
/**
@@ -258,6 +268,23 @@
}
/**
+ * Set the carrier ID of the network operator. The carrier ID associates a Suggested
+ * network with a specific carrier (and therefore SIM). The carrier ID must be provided
+ * for any network which uses the SIM-based authentication: e.g. EAP-SIM, EAP-AKA,
+ * EAP-AKA', and EAP-PEAP with SIM-based phase 2 authentication.
+ * @param carrierId see {@link TelephonyManager#getSimCarrierId()}.
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING)
+ public @NonNull Builder setCarrierId(int carrierId) {
+ mCarrierId = carrierId;
+ return this;
+ }
+
+ /**
* Specifies whether this represents a hidden network.
* <p>
* <li>If not set, defaults to false (i.e not a hidden network).</li>
@@ -380,6 +407,7 @@
wifiConfiguration.meteredOverride =
mIsMetered ? WifiConfiguration.METERED_OVERRIDE_METERED
: WifiConfiguration.METERED_OVERRIDE_NONE;
+ wifiConfiguration.carrierId = mCarrierId;
return wifiConfiguration;
}
@@ -405,6 +433,7 @@
wifiConfiguration.meteredOverride =
mIsMetered ? WifiConfiguration.METERED_OVERRIDE_METERED
: WifiConfiguration.METERED_OVERRIDE_NONE;
+ mPasspointConfiguration.setCarrierId(mCarrierId);
return wifiConfiguration;
}
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 21189a4..67993e1 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -19,7 +19,6 @@
import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
@@ -134,14 +133,14 @@
* @hide
*/
@SystemApi
- @Nullable
+ @NonNull
@RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
public List<Integer> getAvailableChannels(@WifiBand int band) {
try {
Bundle bundle = mService.getAvailableChannels(band, mContext.getOpPackageName());
return bundle.getIntegerArrayList(GET_AVAILABLE_CHANNELS_EXTRA);
} catch (RemoteException e) {
- return null;
+ throw e.rethrowFromSystemServer();
}
}
@@ -344,7 +343,7 @@
}
/** Implement the Parcelable interface {@hide} */
- public static final @android.annotation.NonNull Creator<ScanSettings> CREATOR =
+ public static final @NonNull Creator<ScanSettings> CREATOR =
new Creator<ScanSettings>() {
public ScanSettings createFromParcel(Parcel in) {
ScanSettings settings = new ScanSettings();
@@ -492,7 +491,7 @@
}
/** Implement the Parcelable interface {@hide} */
- public static final @android.annotation.NonNull Creator<ScanData> CREATOR =
+ public static final @NonNull Creator<ScanData> CREATOR =
new Creator<ScanData>() {
public ScanData createFromParcel(Parcel in) {
int id = in.readInt();
@@ -541,7 +540,7 @@
}
/** Implement the Parcelable interface {@hide} */
- public static final @android.annotation.NonNull Creator<ParcelableScanData> CREATOR =
+ public static final @NonNull Creator<ParcelableScanData> CREATOR =
new Creator<ParcelableScanData>() {
public ParcelableScanData createFromParcel(Parcel in) {
int n = in.readInt();
@@ -589,7 +588,7 @@
}
/** Implement the Parcelable interface {@hide} */
- public static final @android.annotation.NonNull Creator<ParcelableScanResults> CREATOR =
+ public static final @NonNull Creator<ParcelableScanResults> CREATOR =
new Creator<ParcelableScanResults>() {
public ParcelableScanResults createFromParcel(Parcel in) {
int n = in.readInt();
@@ -720,7 +719,7 @@
}
/** Implement the Parcelable interface {@hide} */
- public static final @android.annotation.NonNull Creator<PnoSettings> CREATOR =
+ public static final @NonNull Creator<PnoSettings> CREATOR =
new Creator<PnoSettings>() {
public PnoSettings createFromParcel(Parcel in) {
PnoSettings settings = new PnoSettings();
@@ -1068,7 +1067,7 @@
}
/** Implement the Parcelable interface {@hide} */
- public static final @android.annotation.NonNull Creator<WifiChangeSettings> CREATOR =
+ public static final @NonNull Creator<WifiChangeSettings> CREATOR =
new Creator<WifiChangeSettings>() {
public WifiChangeSettings createFromParcel(Parcel in) {
return new WifiChangeSettings();
@@ -1179,7 +1178,7 @@
}
/** Implement the Parcelable interface {@hide} */
- public static final @android.annotation.NonNull Creator<HotlistSettings> CREATOR =
+ public static final @NonNull Creator<HotlistSettings> CREATOR =
new Creator<HotlistSettings>() {
public HotlistSettings createFromParcel(Parcel in) {
HotlistSettings settings = new HotlistSettings();
@@ -1412,7 +1411,7 @@
}
/** Implement the Parcelable interface {@hide} */
- public static final @android.annotation.NonNull Creator<OperationResult> CREATOR =
+ public static final @NonNull Creator<OperationResult> CREATOR =
new Creator<OperationResult>() {
public OperationResult createFromParcel(Parcel in) {
int reason = in.readInt();
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index e9aa076..5befb54 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -24,6 +24,7 @@
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -398,6 +399,30 @@
}
/**
+ * The carrier ID identifies the operator who provides this network configuration.
+ * see {@link TelephonyManager#getSimCarrierId()}
+ */
+ private int mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+
+ /**
+ * Set the carrier ID associated with current configuration.
+ * @param carrierId {@code mCarrierId}
+ * @hide
+ */
+ public void setCarrierId(int carrierId) {
+ this.mCarrierId = carrierId;
+ }
+
+ /**
+ * Get the carrier ID associated with current configuration.
+ * @return {@code mCarrierId}
+ * @hide
+ */
+ public int getCarrierId() {
+ return mCarrierId;
+ }
+
+ /**
* Constructor for creating PasspointConfiguration with default values.
*/
public PasspointConfiguration() {}
@@ -438,6 +463,7 @@
mUsageLimitUsageTimePeriodInMinutes = source.mUsageLimitUsageTimePeriodInMinutes;
mServiceFriendlyNames = source.mServiceFriendlyNames;
mAaaServerTrustedNames = source.mAaaServerTrustedNames;
+ mCarrierId = source.mCarrierId;
}
@Override
@@ -466,6 +492,7 @@
bundle.putSerializable("serviceFriendlyNames",
(HashMap<String, String>) mServiceFriendlyNames);
dest.writeBundle(bundle);
+ dest.writeInt(mCarrierId);
}
@Override
@@ -495,6 +522,7 @@
&& mUsageLimitStartTimeInMillis == that.mUsageLimitStartTimeInMillis
&& mUsageLimitDataLimit == that.mUsageLimitDataLimit
&& mUsageLimitTimeLimitInMinutes == that.mUsageLimitTimeLimitInMinutes
+ && mCarrierId == that.mCarrierId
&& (mServiceFriendlyNames == null ? that.mServiceFriendlyNames == null
: mServiceFriendlyNames.equals(that.mServiceFriendlyNames));
}
@@ -505,7 +533,7 @@
mUpdateIdentifier, mCredentialPriority, mSubscriptionCreationTimeInMillis,
mSubscriptionExpirationTimeInMillis, mUsageLimitUsageTimePeriodInMinutes,
mUsageLimitStartTimeInMillis, mUsageLimitDataLimit, mUsageLimitTimeLimitInMinutes,
- mServiceFriendlyNames);
+ mServiceFriendlyNames, mCarrierId);
}
@Override
@@ -558,6 +586,7 @@
if (mServiceFriendlyNames != null) {
builder.append("ServiceFriendlyNames: ").append(mServiceFriendlyNames);
}
+ builder.append("CarrierId:" + mCarrierId);
return builder.toString();
}
@@ -662,6 +691,7 @@
Map<String, String> friendlyNamesMap = (HashMap) bundle.getSerializable(
"serviceFriendlyNames");
config.setServiceFriendlyNames(friendlyNamesMap);
+ config.mCarrierId = in.readInt();
return config;
}
diff --git a/wifi/java/com/android/server/wifi/BaseWifiService.java b/wifi/java/com/android/server/wifi/BaseWifiService.java
index 5e6c107..4b7d205 100644
--- a/wifi/java/com/android/server/wifi/BaseWifiService.java
+++ b/wifi/java/com/android/server/wifi/BaseWifiService.java
@@ -32,6 +32,7 @@
import android.net.wifi.ITxPacketCountListener;
import android.net.wifi.IWifiManager;
import android.net.wifi.ScanResult;
+import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiActivityEnergyInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
@@ -293,8 +294,15 @@
throw new UnsupportedOperationException();
}
- @Override
+ /** @deprecated replaced by newer signature */
+ @Deprecated
public int startLocalOnlyHotspot(ILocalOnlyHotspotCallback callback, String packageName) {
+ return startLocalOnlyHotspot(callback, packageName, null);
+ }
+
+ @Override
+ public int startLocalOnlyHotspot(ILocalOnlyHotspotCallback callback, String packageName,
+ SoftApConfiguration customConfig) {
throw new UnsupportedOperationException();
}
diff --git a/wifi/tests/src/android/net/wifi/ScanResultTest.java b/wifi/tests/src/android/net/wifi/ScanResultTest.java
index 54ec325..b5c74d1 100644
--- a/wifi/tests/src/android/net/wifi/ScanResultTest.java
+++ b/wifi/tests/src/android/net/wifi/ScanResultTest.java
@@ -21,6 +21,7 @@
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.validateMockitoUsage;
+import android.net.wifi.ScanResult.InformationElement;
import android.os.Parcel;
import androidx.test.filters.SmallTest;
@@ -41,6 +42,8 @@
public static final int TEST_LEVEL = -56;
public static final int TEST_FREQUENCY = 2412;
public static final long TEST_TSF = 04660l;
+ public static final @ScanResult.WifiStandard int TEST_WIFI_STANDARD =
+ ScanResult.WIFI_STANDARD_11AC;
/**
* Setup before tests.
@@ -124,17 +127,38 @@
}
/**
+ * Verify parcel read/write for ScanResult with Information Element
+ */
+ @Test
+ public void verifyScanResultParcelWithInformationElement() throws Exception {
+ ScanResult writeScanResult = createScanResult();
+ writeScanResult.informationElements = new ScanResult.InformationElement[2];
+ writeScanResult.informationElements[0] = new ScanResult.InformationElement();
+ writeScanResult.informationElements[0].id = InformationElement.EID_HT_OPERATION;
+ writeScanResult.informationElements[0].idExt = 0;
+ writeScanResult.informationElements[0].bytes = new byte[]{0x11, 0x22, 0x33};
+ writeScanResult.informationElements[1] = new ScanResult.InformationElement();
+ writeScanResult.informationElements[1].id = InformationElement.EID_EXTENSION_PRESENT;
+ writeScanResult.informationElements[1].idExt = InformationElement.EID_EXT_HE_OPERATION;
+ writeScanResult.informationElements[1].bytes = new byte[]{0x44, 0x55, 0x66};
+ ScanResult readScanResult = new ScanResult(writeScanResult);
+ assertScanResultEquals(writeScanResult, readScanResult);
+ }
+
+ /**
* Verify toString for ScanResult.
*/
@Test
public void verifyScanResultToStringWithoutRadioChainInfo() throws Exception {
ScanResult scanResult = createScanResult();
- assertEquals("SSID: \"test_ssid\", BSSID: 04:ac:fe:45:34:10, capabilities: CCMP, " +
- "level: -56, frequency: 2412, timestamp: 2480, distance: 0(cm), distanceSd: 0(cm), " +
- "passpoint: no, ChannelBandwidth: 0, centerFreq0: 0, centerFreq1: 0, " +
- "80211mcResponder: is not supported, Carrier AP: no, " +
- "Carrier AP EAP Type: 0, Carrier name: null, " +
- "Radio Chain Infos: null", scanResult.toString());
+ assertEquals("SSID: \"test_ssid\", BSSID: 04:ac:fe:45:34:10, capabilities: CCMP, "
+ + "level: -56, frequency: 2412, timestamp: 2480, "
+ + "distance: 0(cm), distanceSd: 0(cm), "
+ + "passpoint: no, ChannelBandwidth: 0, centerFreq0: 0, centerFreq1: 0, "
+ + "standard: 11ac, "
+ + "80211mcResponder: is not supported, Carrier AP: no, "
+ + "Carrier AP EAP Type: 0, Carrier name: null, "
+ + "Radio Chain Infos: null", scanResult.toString());
}
/**
@@ -150,13 +174,15 @@
scanResult.radioChainInfos[1] = new ScanResult.RadioChainInfo();
scanResult.radioChainInfos[1].id = 1;
scanResult.radioChainInfos[1].level = -54;
- assertEquals("SSID: \"test_ssid\", BSSID: 04:ac:fe:45:34:10, capabilities: CCMP, " +
- "level: -56, frequency: 2412, timestamp: 2480, distance: 0(cm), distanceSd: 0(cm), " +
- "passpoint: no, ChannelBandwidth: 0, centerFreq0: 0, centerFreq1: 0, " +
- "80211mcResponder: is not supported, Carrier AP: no, " +
- "Carrier AP EAP Type: 0, Carrier name: null, " +
- "Radio Chain Infos: [RadioChainInfo: id=0, level=-45, " +
- "RadioChainInfo: id=1, level=-54]", scanResult.toString());
+ assertEquals("SSID: \"test_ssid\", BSSID: 04:ac:fe:45:34:10, capabilities: CCMP, "
+ + "level: -56, frequency: 2412, timestamp: 2480, distance: 0(cm), "
+ + "distanceSd: 0(cm), "
+ + "passpoint: no, ChannelBandwidth: 0, centerFreq0: 0, centerFreq1: 0, "
+ + "standard: 11ac, "
+ + "80211mcResponder: is not supported, Carrier AP: no, "
+ + "Carrier AP EAP Type: 0, Carrier name: null, "
+ + "Radio Chain Infos: [RadioChainInfo: id=0, level=-45, "
+ + "RadioChainInfo: id=1, level=-54]", scanResult.toString());
}
/**
@@ -177,6 +203,7 @@
result.level = TEST_LEVEL;
result.frequency = TEST_FREQUENCY;
result.timestamp = TEST_TSF;
+ result.setWifiStandard(TEST_WIFI_STANDARD);
return result;
}
@@ -187,6 +214,8 @@
assertEquals(expected.level, actual.level);
assertEquals(expected.frequency, actual.frequency);
assertEquals(expected.timestamp, actual.timestamp);
+ assertEquals(expected.getWifiStandard(), actual.getWifiStandard());
assertArrayEquals(expected.radioChainInfos, actual.radioChainInfos);
+ assertArrayEquals(expected.informationElements, actual.informationElements);
}
}
diff --git a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
new file mode 100644
index 0000000..949b479
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.net.MacAddress;
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+@SmallTest
+public class SoftApConfigurationTest {
+ private SoftApConfiguration parcelUnparcel(SoftApConfiguration configIn) {
+ Parcel parcel = Parcel.obtain();
+ parcel.writeParcelable(configIn, 0);
+ parcel.setDataPosition(0);
+ SoftApConfiguration configOut =
+ parcel.readParcelable(SoftApConfiguration.class.getClassLoader());
+ parcel.recycle();
+ return configOut;
+ }
+
+ @Test
+ public void testBasicSettings() {
+ SoftApConfiguration original = new SoftApConfiguration.Builder()
+ .setSsid("ssid")
+ .setBssid(MacAddress.fromString("11:22:33:44:55:66"))
+ .build();
+ assertThat(original.getSsid()).isEqualTo("ssid");
+ assertThat(original.getBssid()).isEqualTo(MacAddress.fromString("11:22:33:44:55:66"));
+ assertThat(original.getWpa2Passphrase()).isNull();
+
+ SoftApConfiguration unparceled = parcelUnparcel(original);
+ assertThat(unparceled).isNotSameAs(original);
+ assertThat(unparceled).isEqualTo(original);
+ assertThat(unparceled.hashCode()).isEqualTo(original.hashCode());
+
+ SoftApConfiguration copy = new SoftApConfiguration.Builder(original).build();
+ assertThat(copy).isNotSameAs(original);
+ assertThat(copy).isEqualTo(original);
+ assertThat(copy.hashCode()).isEqualTo(original.hashCode());
+ }
+
+ @Test
+ public void testWpa2() {
+ SoftApConfiguration original = new SoftApConfiguration.Builder()
+ .setWpa2Passphrase("secretsecret")
+ .build();
+ assertThat(original.getWpa2Passphrase()).isEqualTo("secretsecret");
+
+ SoftApConfiguration unparceled = parcelUnparcel(original);
+ assertThat(unparceled).isNotSameAs(original);
+ assertThat(unparceled).isEqualTo(original);
+ assertThat(unparceled.hashCode()).isEqualTo(original.hashCode());
+
+ SoftApConfiguration copy = new SoftApConfiguration.Builder(original).build();
+ assertThat(copy).isNotSameAs(original);
+ assertThat(copy).isEqualTo(original);
+ assertThat(copy.hashCode()).isEqualTo(original.hashCode());
+ }
+}
diff --git a/wifi/tests/src/android/net/wifi/SoftApInfoTest.java b/wifi/tests/src/android/net/wifi/SoftApInfoTest.java
new file mode 100644
index 0000000..929f3ab
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/SoftApInfoTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import android.os.Parcel;
+
+import static org.junit.Assert.assertEquals;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.SoftApInfo}.
+ */
+@SmallTest
+public class SoftApInfoTest {
+
+ /**
+ * Verifies copy constructor.
+ */
+ @Test
+ public void testCopyOperator() throws Exception {
+ SoftApInfo info = new SoftApInfo();
+ info.setFrequency(2412);
+ info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ);
+
+ SoftApInfo copiedInfo = new SoftApInfo(info);
+
+ assertEquals(info, copiedInfo);
+ assertEquals(info.hashCode(), copiedInfo.hashCode());
+ }
+
+ /**
+ * Verifies parcel serialization/deserialization.
+ */
+ @Test
+ public void testParcelOperation() throws Exception {
+ SoftApInfo info = new SoftApInfo();
+ info.setFrequency(2412);
+ info.setBandwidth(SoftApInfo.CHANNEL_WIDTH_20MHZ);
+
+ Parcel parcelW = Parcel.obtain();
+ info.writeToParcel(parcelW, 0);
+ byte[] bytes = parcelW.marshall();
+ parcelW.recycle();
+
+ Parcel parcelR = Parcel.obtain();
+ parcelR.unmarshall(bytes, 0, bytes.length);
+ parcelR.setDataPosition(0);
+ SoftApInfo fromParcel = SoftApInfo.CREATOR.createFromParcel(parcelR);
+
+ assertEquals(info, fromParcel);
+ assertEquals(info.hashCode(), fromParcel.hashCode());
+ }
+
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiInfoTest.java b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
index ea08ea8..22a5faa 100644
--- a/wifi/tests/src/android/net/wifi/WifiInfoTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
@@ -38,7 +38,7 @@
private static final String TEST_PACKAGE_NAME = "com.test.example";
private static final String TEST_FQDN = "test.com";
private static final String TEST_PROVIDER_NAME = "test";
- private static final int TEST_WIFI_TECHNOLOGY = WifiInfo.WIFI_TECHNOLOGY_11AC;
+ private static final int TEST_WIFI_STANDARD = ScanResult.WIFI_STANDARD_11AC;
/**
* Verify parcel write/read with WifiInfo.
@@ -55,7 +55,7 @@
writeWifiInfo.setFQDN(TEST_FQDN);
writeWifiInfo.setProviderFriendlyName(TEST_PROVIDER_NAME);
writeWifiInfo.setNetworkSuggestionOrSpecifierPackageName(TEST_PACKAGE_NAME);
- writeWifiInfo.setWifiTechnology(TEST_WIFI_TECHNOLOGY);
+ writeWifiInfo.setWifiStandard(TEST_WIFI_STANDARD);
Parcel parcel = Parcel.obtain();
writeWifiInfo.writeToParcel(parcel, 0);
@@ -74,6 +74,6 @@
assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getNetworkSuggestionOrSpecifierPackageName());
assertEquals(TEST_FQDN, readWifiInfo.getPasspointFqdn());
assertEquals(TEST_PROVIDER_NAME, readWifiInfo.getPasspointProviderFriendlyName());
- assertEquals(TEST_WIFI_TECHNOLOGY, readWifiInfo.getWifiTechnology());
+ assertEquals(TEST_WIFI_STANDARD, readWifiInfo.getWifiStandard());
}
}
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 8d0579b..14e994c 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -97,6 +97,8 @@
private static final String TEST_PACKAGE_NAME = "TestPackage";
private static final String TEST_COUNTRY_CODE = "US";
private static final String[] TEST_MAC_ADDRESSES = {"da:a1:19:0:0:0"};
+ private static final int TEST_AP_FREQUENCY = 2412;
+ private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ;
@Mock Context mContext;
@Mock android.net.wifi.IWifiManager mWifiService;
@@ -122,7 +124,6 @@
mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo);
when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME);
-
mWifiManager = new WifiManager(mContext, mWifiService, mLooper.getLooper());
verify(mWifiService).getVerboseLoggingLevel();
}
@@ -173,7 +174,7 @@
public void testCreationAndCloseOfLocalOnlyHotspotReservation() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
- anyString())).thenReturn(REQUEST_REGISTERED);
+ anyString(), eq(null))).thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(mApConfig));
@@ -191,7 +192,7 @@
throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
- anyString())).thenReturn(REQUEST_REGISTERED);
+ anyString(), eq(null))).thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(mApConfig));
@@ -351,7 +352,7 @@
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
verify(mWifiService)
- .startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString());
+ .startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(), eq(null));
}
/**
@@ -362,7 +363,7 @@
public void testStartLocalOnlyHotspotThrowsSecurityException() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
doThrow(new SecurityException()).when(mWifiService)
- .startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString());
+ .startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(), eq(null));
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
}
@@ -374,7 +375,7 @@
public void testStartLocalOnlyHotspotThrowsIllegalStateException() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
doThrow(new IllegalStateException()).when(mWifiService)
- .startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString());
+ .startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(), eq(null));
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
}
@@ -385,7 +386,7 @@
public void testCorrectLooperIsUsedForHandler() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
- anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE);
+ anyString(), eq(null))).thenReturn(ERROR_INCOMPATIBLE_MODE);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mLooper.dispatchAll();
assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
@@ -404,7 +405,7 @@
when(mContext.getMainExecutor()).thenReturn(altLooper.getNewExecutor());
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
- anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE);
+ anyString(), eq(null))).thenReturn(ERROR_INCOMPATIBLE_MODE);
mWifiManager.startLocalOnlyHotspot(callback, null);
altLooper.dispatchAll();
assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
@@ -423,7 +424,7 @@
Handler callbackHandler = new Handler(callbackLooper.getLooper());
ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
- when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString()))
+ when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(), eq(null)))
.thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
callbackLooper.dispatchAll();
@@ -449,7 +450,7 @@
Handler callbackHandler = new Handler(callbackLooper.getLooper());
ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
- when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString()))
+ when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(), eq(null)))
.thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
callbackLooper.dispatchAll();
@@ -474,7 +475,7 @@
Handler callbackHandler = new Handler(callbackLooper.getLooper());
ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
- when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString()))
+ when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(), eq(null)))
.thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
callbackLooper.dispatchAll();
@@ -497,7 +498,7 @@
Handler callbackHandler = new Handler(callbackLooper.getLooper());
ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
- when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString()))
+ when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(), eq(null)))
.thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
callbackLooper.dispatchAll();
@@ -517,7 +518,7 @@
public void testLocalOnlyHotspotCallbackFullOnIncompatibleMode() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
- anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE);
+ anyString(), eq(null))).thenReturn(ERROR_INCOMPATIBLE_MODE);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mLooper.dispatchAll();
assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
@@ -533,7 +534,7 @@
public void testLocalOnlyHotspotCallbackFullOnTetheringDisallowed() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
- anyString())).thenReturn(ERROR_TETHERING_DISALLOWED);
+ anyString(), eq(null))).thenReturn(ERROR_TETHERING_DISALLOWED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mLooper.dispatchAll();
assertEquals(ERROR_TETHERING_DISALLOWED, callback.mFailureReason);
@@ -550,7 +551,7 @@
public void testLocalOnlyHotspotCallbackFullOnSecurityException() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
doThrow(new SecurityException()).when(mWifiService)
- .startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString());
+ .startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(), eq(null));
try {
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
} catch (SecurityException e) {
@@ -571,7 +572,7 @@
public void testLocalOnlyHotspotCallbackFullOnNoChannelError() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
- anyString())).thenReturn(REQUEST_REGISTERED);
+ anyString(), eq(null))).thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mLooper.dispatchAll();
//assertEquals(ERROR_NO_CHANNEL, callback.mFailureReason);
@@ -587,7 +588,7 @@
public void testCancelLocalOnlyHotspotRequestCallsStopOnWifiService() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
- anyString())).thenReturn(REQUEST_REGISTERED);
+ anyString(), eq(null))).thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mWifiManager.cancelLocalOnlyHotspotRequest();
verify(mWifiService).stopLocalOnlyHotspot();
@@ -609,7 +610,7 @@
public void testCallbackAfterLocalOnlyHotspotWasCancelled() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
- anyString())).thenReturn(REQUEST_REGISTERED);
+ anyString(), eq(null))).thenReturn(REQUEST_REGISTERED);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mWifiManager.cancelLocalOnlyHotspotRequest();
verify(mWifiService).stopLocalOnlyHotspot();
@@ -628,7 +629,7 @@
public void testCancelAfterLocalOnlyHotspotCallbackTriggered() throws Exception {
TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
- anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE);
+ anyString(), eq(null))).thenReturn(ERROR_INCOMPATIBLE_MODE);
mWifiManager.startLocalOnlyHotspot(callback, mHandler);
mLooper.dispatchAll();
assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
@@ -639,6 +640,17 @@
verify(mWifiService, never()).stopLocalOnlyHotspot();
}
+ @Test
+ public void testStartLocalOnlyHotspotForwardsCustomConfig() throws Exception {
+ SoftApConfiguration customConfig = new SoftApConfiguration.Builder()
+ .setSsid("customSsid")
+ .build();
+ TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
+ mWifiManager.startLocalOnlyHotspot(customConfig, mExecutor, callback);
+ verify(mWifiService).startLocalOnlyHotspot(
+ any(ILocalOnlyHotspotCallback.class), anyString(), eq(customConfig));
+ }
+
/**
* Verify the watchLocalOnlyHotspot call goes to WifiServiceImpl.
*/
@@ -765,11 +777,34 @@
verify(mSoftApCallback).onConnectedClientsChanged(testClients);
}
+
+ /*
+ * Verify client-provided callback is being called through callback proxy
+ */
+ @Test
+ public void softApCallbackProxyCallsOnSoftApInfoChanged() throws Exception {
+ SoftApInfo testSoftApInfo = new SoftApInfo();
+ testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
+ testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
+ ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
+ ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
+ mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
+ verify(mWifiService).registerSoftApCallback(any(IBinder.class), callbackCaptor.capture(),
+ anyInt());
+
+ callbackCaptor.getValue().onInfoChanged(testSoftApInfo);
+ mLooper.dispatchAll();
+ verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
+ }
+
/*
* Verify client-provided callback is being called through callback proxy on multiple events
*/
@Test
public void softApCallbackProxyCallsOnMultipleUpdates() throws Exception {
+ SoftApInfo testSoftApInfo = new SoftApInfo();
+ testSoftApInfo.setFrequency(TEST_AP_FREQUENCY);
+ testSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH);
ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
mWifiManager.registerSoftApCallback(mSoftApCallback, mHandler);
@@ -779,11 +814,13 @@
final List<WifiClient> testClients = new ArrayList();
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0);
callbackCaptor.getValue().onConnectedClientsChanged(testClients);
+ callbackCaptor.getValue().onInfoChanged(testSoftApInfo);
callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
mLooper.dispatchAll();
verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0);
verify(mSoftApCallback).onConnectedClientsChanged(testClients);
+ verify(mSoftApCallback).onInfoChanged(testSoftApInfo);
verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
}